基本知识,循环的灵活使用~~~

sxldfang 2014-09-25 04:27:08

有人开发个程序以产生一些“标号”,采用了多重循环,如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace 多重循环
{
class Program
{
static void Main(string[] args)
{
int i, j, k;
string s = "ABCDE";
for (i = 0; i <3; ++i)
{
for (j = 0; j < 3; ++j)
{
for (k = 0; k < 2; ++k)
{
Console.WriteLine("{0}{1}{2}", s[i], s[j], k);
}
}
}

Console.ReadKey();
}
}
}

运行结果:
AA0
AA1
AB0
AB1
AC0
AC1
BA0
BA1
BB0
BB1
BC0
BC1
CA0
CA1
CB0
CB1
CC0
CC1


上面的每个标号只有三位,位数太少,标号数量不够用,问能否多产生几位?

这里面可能包含有两层含义:

1、多写几层循环当然可以,有无更简单的方法?

2、循环几次不确定,能否完成这样的循环?

其实,一层层的去嵌套循环确实不必要,下面就可简单地解决上面的问题:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace 多重循环
{
class Program
{
static void Main(string[] args)
{
string s1 = "AB";
string s2 = "123";
string[] s = new string[] { s1, s1, s1, s2 };//可定义每一位可用的字符
mulLoop(s);
Console.ReadKey();
}

static void mulLoop(string[] s)
{
int[] mark = new int[s.Length];
int p = 0;

while (p>=0)
{
for (int i = 0; i < s.Length; ++i)
{
Console.Write(s[i][mark[i]]);
}
Console.WriteLine();

p = mark.Length - 1;
while (p >= 0)
{
++mark[p];
if (mark[p] < s[p].Length) break;
mark[p] = 0;
--p;
}
}
}
}
}

运行结果如下:
AAA1
AAA2
AAA3
AAB1
AAB2
AAB3
ABA1
ABA2
ABA3
ABB1
ABB2
ABB3
BAA1
BAA2
BAA3
BAB1
BAB2
BAB3
BBA1
BBA2
BBA3
BBB1
BBB2
BBB3


...全文
380 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
sxldfang 2014-09-30
  • 打赏
  • 举报
回复
感谢楼上各位的见解,能从不同的见解中获取点滴就是一种收获~~~
sxldfang 2014-09-30
  • 打赏
  • 举报
回复
引用 9 楼 Z65443344 的回复:
并不是代码行数少就简单,行数多就不简单 简单有2种含义: 1.可读性强,看代码就能直观的看出逻辑,反过来,有了逻辑,很容易的用代码实现 2.复杂度低,执行效率高
表示赞同~~~ 当时那位想做36重循环以产生36位的标号,请问你会去写36重循环吗?我是不会那样做,虽然很简单。。。
sxldfang 2014-09-30
  • 打赏
  • 举报
回复
引用 7 楼 zhi_ai_yaya 的回复:
Console.WriteLine("{0}{1}{2}", s[i], s[j], k); 貌似这样使用,有格式化参数的个数限制,超过4个就不行了。就是只能有{0}{1}{2}{3}。
你试试这个? Console.WriteLine("{0}{1}{2}{4}{5}{6}{7}{8}{9}", 0, 1, 2, 3, 4, 5, 6, 7, 8, 9);
於黾 2014-09-30
  • 打赏
  • 举报
回复
递归消耗资源,你得看用递归干什么活 为了几个字节的资源,费那么大尽,值得吗
sxldfang 2014-09-30
  • 打赏
  • 举报
回复
引用 6 楼 sp1234 的回复:
能用大白话把算法说清楚、让没有写过代码(但是受过高等教育)的人也能明白,这才是第一位的素质。
表示非常赞同~~~
sxldfang 2014-09-30
  • 打赏
  • 举报
回复
引用 5 楼 effun 的回复:
这段代码是按你第二个示例的逻辑写的,即其模式为[AB]*[123]。 原理很简单,用一个Int32来表示一个标号,通过Int32的每个位来描述一个字符,0表示A,1表示B。但由于标号最后一位有三个字符,因此需要有2位来表示。Int32一共32位,除去最高的符号位以外,最多可以生成30个字符长度的标号。
思路不错,不过应用受限~~~
sxldfang 2014-09-30
  • 打赏
  • 举报
回复
引用 1 楼 Z65443344 的回复:
做个递归不行?
每次递归都会消耗一些资源,不用递归能解决的就别用递归了吧! 当然,递归可简化算法,思路明晰,用的地方也很多~~~
漫天雪飞 2014-09-27
  • 打赏
  • 举报
回复
小板凳
puler 2014-09-27
  • 打赏
  • 举报
回复
可取性很高,估计要稍微改一下适合自己的循环习惯
我叫小菜菜 2014-09-26
  • 打赏
  • 举报
回复
Console.WriteLine("{0}{1}{2}", s[i], s[j], k); 貌似这样使用,有格式化参数的个数限制,超过4个就不行了。就是只能有{0}{1}{2}{3}。
a3212b12 2014-09-26
  • 打赏
  • 举报
回复
引用 6 楼 sp1234 的回复:
[ 其实你根本没有“用中文”来清洗地表达出来算法!
说的太正确。 本问题的关键是 1 到底几位,位数是固定长度还是可变长度。 2 每位的取值字符是什么(字母还是数字还是可以一个有序的字符序列)?变化的规律是什么(按字母、按数字、递增还是递减)? --------------- 楼主改进的代码 技巧的地方就是这里

 string s1 = "AB";
            string s2 = "123";
            string[] s = new string[] { s1, s1, s1, s2 };//可定义每一位可用的字符
用这样的模式实现了可变位数、可变每位字符集
於黾 2014-09-26
  • 打赏
  • 举报
回复
当然,如果有现成的方法可以调用,那么就会既可读性强,又代码少 比如用linq
於黾 2014-09-26
  • 打赏
  • 举报
回复
引用 8 楼 a3212b12 的回复:
上面的每个标号只有三位,位数太少,标号数量不够用,问能否多产生几位? 这里面可能包含有两层含义: 1、多写几层循环当然可以,有无更简单的方法? 2、循环几次不确定,能否完成这样的循环? ------------------------------------------------- 逻辑有问题: 1 能否多产生几位,怎么就包含了要对源程序进行简化的含义。 2 即便是要求用更简单的方法来实现,不见得1层循环的方法比多层循环更简单。就楼主的两段代码来说,不论是从代码的长度还是逻辑的复杂性来说,前面的代码明显比后面的代码简单。
+1 并不是代码行数少就简单,行数多就不简单 简单有2种含义: 1.可读性强,看代码就能直观的看出逻辑,反过来,有了逻辑,很容易的用代码实现 2.复杂度低,执行效率高
a3212b12 2014-09-26
  • 打赏
  • 举报
回复
上面的每个标号只有三位,位数太少,标号数量不够用,问能否多产生几位? 这里面可能包含有两层含义: 1、多写几层循环当然可以,有无更简单的方法? 2、循环几次不确定,能否完成这样的循环? ------------------------------------------------- 逻辑有问题: 1 能否多产生几位,怎么就包含了要对源程序进行简化的含义。 2 即便是要求用更简单的方法来实现,不见得1层循环的方法比多层循环更简单。就楼主的两段代码来说,不论是从代码的长度还是逻辑的复杂性来说,前面的代码明显比后面的代码简单。
a3212b12 2014-09-26
  • 打赏
  • 举报
回复
引用 12 楼 iyomumx 的回复:
每个int对应一个标号的思想才是正道
这种问题相当于进制转换,只不过每位的进制不一样


中午要吃饭,所以没有全部来得及写完,下午再来,发现此位兄弟已经抓住了根本。

-----------------------
编号确实就是进制问题,而且一套编号系统好不好,不仅仅是生成码的时候简单,其他系统调用也必须简单,结果就 不是说编几个循环一次把编码输出就行了,其他系统调用的时候,往往是需要下一个编码是多少,这就是iyomumx 说的 每个int对应一个标号。
下面发上我的代码,只有序号得到编码部分,原理和iyomumx 差不多。技巧就没有iyomumx 使用的多了。


Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click


Try

Dim num1 As Integer = Me.TextBox1.Text
Me.ListBox1.Items.Clear()

Dim ii As Integer
For ii = 1 To num1
Me.ListBox1.Items.Add(ii & "编号 = " & to26(ii, 6))
Next

Catch e1 As Exception
Dim mName As String
mName = System.Reflection.MethodBase.GetCurrentMethod().Name()
MsgBox("在" & Me.GetType.FullName & "的" & mName & "中出现错误:" & ControlChars.CrLf & ControlChars.CrLf & e1.Message, MsgBoxStyle.Exclamation)



End Try
End Sub


Public Function to26(ByVal num1 As Integer, ByVal len As Integer) As String
Dim A_n As Integer
A_n = Asc("A")

Dim v1 As Integer
Dim x As Integer
Dim y As Integer

Dim str_o As String = ""

v1 = num1
While v1 > 0
x = v1 \ 26
y = v1 Mod 26

Dim str1 As String
Dim s_n As Integer
If y = 0 Then
s_n = A_n - 1 + 26
str1 = Chr(s_n)
x = x - 1
Else
s_n = A_n - 1 + y
str1 = Chr(s_n)
End If

str_o = str1 & str_o

v1 = x
End While


str_o = str_o.PadLeft(len, " ")
Return str_o
End Function


Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
Try

Dim num1 As Integer = Me.TextBox2.Text
Me.TextBox3.Text = (to26(num1, 6))

Catch e1 As Exception
Dim mName As String
mName = System.Reflection.MethodBase.GetCurrentMethod().Name()
MsgBox("在" & Me.GetType.FullName & "的" & mName & "中出现错误:" & ControlChars.CrLf & ControlChars.CrLf & e1.Message, MsgBoxStyle.Exclamation)



End Try
End Sub


iyomumx 2014-09-26
  • 打赏
  • 举报
回复
我觉得楼主的代码算不上可读性强,5L的每个int对应一个标号的思想才是正道 自己写的int->标号/标号->int:
//假设dic中每个字符串没有重复字符
static string IntegerToSN(string[] dic, int num)
{
    char[] result = new char[dic.Length];
    for (int i = dic.Length - 1; i >= 0; i--)
    {
        result[i] = dic[i][num % dic[i].Length];
        num /= dic[i].Length;
    }
    return new string(result);
}

static int SNToInteger(string[] dic, string sn)
{
    int result = 0;
    for (int i = 0; i < dic.Length; i++)
    {
        result *= dic[i].Length;
        result += dic[i].IndexOf(sn[i]);
    }
    return result;
}
这种问题相当于进制转换,只不过每位的进制不一样
  • 打赏
  • 举报
回复
引用 楼主 sxldfang 的回复:
[code=csharp] 有人开发个程序以产生一些“标号”,采用了多重循环,如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 多重循环 { class Program { static void Main(string[] args) { int i, j, k; string s = "ABCDE"; for (i = 0; i <3; ++i) { for (j = 0; j < 3; ++j) { for (k = 0; k < 2; ++k) { Console.WriteLine("{0}{1}{2}", s[i], s[j], k); } } } Console.ReadKey(); } } } 运行结果: AA0 AA1 AB0 AB1 AC0 AC1 BA0 BA1 BB0 BB1 BC0 BC1 CA0 CA1 CB0 CB1 CC0 CC1 上面的每个标号只有三位,位数太少,标号数量不够用,问能否多产生几位? 这里面可能包含有两层含义: 1、多写几层循环当然可以,有无更简单的方法? 2、循环几次不确定,能否完成这样的循环?
其实你根本没有“用中文”来清洗地表达出来算法! 有的人只会写上代码、不会用文字来表达业务逻辑。当跟别人讨论软件设计创意思路时,别人一旦追问某业务逻辑,他就很“怂”地对别人说“我说不清楚,你过来看看我的程序吧,或者我过去给你写代码吧”。其实这就暴露出了问题。写几行代码算什么高级的事情?能用大白话把算法说清楚、让没有写过代码(但是受过高等教育)的人也能明白,这才是第一位的素质。 也许代码写了10年,但是对编程设计方面的基本技术还没有完全掌握。
effun 2014-09-25
  • 打赏
  • 举报
回复
一个循环搞定

    public static string[] GenerateLabels(int length)
    {
        if (length < 1 || length > 30)
            throw new ArgumentOutOfRangeException();

        List<string> list = new List<string>();

        int count = (1 << (length + 1)) - 1;

        for (int i = 0; i < count; i++)
        {
            if ((i % 4) != 3)
            {
                list.Add(Translate(i, length));
            }
        }

        return list.ToArray();
    }

    private static string Translate(int number, int length)
    {
        StringBuilder text = new StringBuilder(length - 1);

        for (int i = length; i > 1; i--)
        {
            text.Append((char)(65 + Math.Sign(number & (1 << i))));
        }

        text.Append((char)(49 + (number & 3)));

        return text.ToString();
    }
这段代码是按你第二个示例的逻辑写的,即其模式为[AB]*[123]。 原理很简单,用一个Int32来表示一个标号,通过Int32的每个位来描述一个字符,0表示A,1表示B。但由于标号最后一位有三个字符,因此需要有2位来表示。Int32一共32位,除去最高的符号位以外,最多可以生成30个字符长度的标号。 GenerateLables是入口函数,参数length表示生成标号的最大长度。 Translate是将Int32转换为相应的标号字符串。 以length=6运行得到如下结果 AAAAA1 AAAAA2 AAAAA3 AAAAB1 AAAAB2 AAAAB3 AAABA1 AAABA2 AAABA3 AAABB1 AAABB2 AAABB3 AABAA1 AABAA2 AABAA3 AABAB1 AABAB2 AABAB3 AABBA1 AABBA2 AABBA3 AABBB1 AABBB2 AABBB3 ABAAA1 ABAAA2 ABAAA3 ABAAB1 ABAAB2 ABAAB3 ABABA1 ABABA2 ABABA3 ABABB1 ABABB2 ABABB3 ABBAA1 ABBAA2 ABBAA3 ABBAB1 ABBAB2 ABBAB3 ABBBA1 ABBBA2 ABBBA3 ABBBB1 ABBBB2 ABBBB3 BAAAA1 BAAAA2 BAAAA3 BAAAB1 BAAAB2 BAAAB3 BAABA1 BAABA2 BAABA3 BAABB1 BAABB2 BAABB3 BABAA1 BABAA2 BABAA3 BABAB1 BABAB2 BABAB3 BABBA1 BABBA2 BABBA3 BABBB1 BABBB2 BABBB3 BBAAA1 BBAAA2 BBAAA3 BBAAB1 BBAAB2 BBAAB3 BBABA1 BBABA2 BBABA3 BBABB1 BBABB2 BBABB3 BBBAA1 BBBAA2 BBBAA3 BBBAB1 BBBAB2 BBBAB3 BBBBA1 BBBBA2 BBBBA3 BBBBB1 BBBBB2 BBBBB3 最后要说一点,因为只有A和B两个字符,程序相对来说简单点,如果有更多的字符就会复杂一些,你可以自己试着去改。
烈火蜓蜻 2014-09-25
  • 打赏
  • 举报
回复
没看懂这个代码, 这个号,按理说,这号,一个循环就可以产生了,需要双重循环吗?
by_封爱 版主 2014-09-25
  • 打赏
  • 举报
回复
加载更多回复(2)

110,546

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧