【问题标题】:scanning a string until ":" [duplicate]扫描字符串直到“:” [重复]
【发布时间】:2016-03-24 08:25:30
【问题描述】:

我正在编写一个代码,我希望它扫描一个名称,直到它到达“:”,但不知何故它继续扫描“:”。 这是我的代码:

char letter, StudentName[1][40];
int j=0;
scanf("%c", &letter);
while (letter != ":")
{
StudentName[1][j] = letter;
j++;
scanf("%c", &letter);
}

此外,虽然代码运行,但我收到一条警告消息:“警告 C4047: '!=' : 'int' 在间接级别上与 'char [2] 不同”

【问题讨论】:

  • 更改StudentName[1][j] = letter; --> StudentName[0][j] = letter; 注意:循环后,添加StudentName[0][j] = '\0';
  • 如果只有1个StudentName,那为什么要做二维数组呢?
  • chux- 为什么要添加 '\0'?不是自动添加的吗?
  • 不,在您的代码中,'\0' 不会自动或显式添加到任何地方。你认为是什么代码自动完成的?在您的 cmets 中使用 @ 前缀名称,否则不会像“@chux”与“chux”一样通知用户

标签: c while-loop scanf


【解决方案1】:

您在 while 循环条件上进行字符串比较而不是字符比较。

您实质上要问的是 ((char *)letter == (char *)"String")。

两件事:

One - 这不是您进行字符串比较的方式。 (参见:strcmp)。

二——你甚至不想做字符串比较,你想做字符比较,所以把双引号改成单引号。

另外,你的字符串甚至不在堆栈上,它在只读部分,因为它是在编译时分配的 - 所以没有堆栈/堆分配的指针永远是相等的:)。

此外,当您分配具有 N 个索引的数组时,您可以访问而不冒访问冲突/分段错误错误风险的最大索引是 N-1,因此你的例子,我会改变这一行:

StudentName[1][j] = letter;

StudentName[0][j] = letter;

而且,为了稳健起见 - 考虑为用户可以插入的输入量设置一个上限(即 - while 循环的另一个条件,限制不超过 sizeof(StudentName) 个字符。)

【讨论】:

    【解决方案2】:

    您可以这样做,您不需要变量字母。或者如果您想使用变量字母,您只需将字符“:”分配给字母并将其与 StudentName 值进行比较

    int i,j;
    for(i=0;i<2;i++){
    for(j=0;j<40;j++){
    if(StudentName[i][j]==':')}break;
    scanf("%c", &StudentName[i][j]);} 
    

    【讨论】:

    • 这会导致很多事情失败:1) for (i = 0; i &lt; 2; i++) .. break. 是一个不需要的 for 循环,并且 2) 不允许调用 scanf("%c", &amp;StudentName[i][j]);。 3) {if(StudentName[i][j]==':')} 是语法错误 4) scanf() 结果未测试。
    【解决方案3】:

    没有理由将StudentName 声明为字符StudentName[1][40]。只需将数组声明为:

    char StudentName[40] = {0};
    

    注意上面,数组也被初始化为包含所有zero's。这是一个养成的好习惯。初始化所有变量是一种好习惯的原因有很多。在这里,通过初始化为0,您可以使用 nul-terminating 字符填充 字符数组(您可能会将其用作 字符串),因此,如果您未能显式终止您的字符串,它会通过您的初始化为您完成。

    接下来在进行字符输入时(一次一个字符),您通常希望使用getcharfgetc 以避免使用scanf 系列函数时固有的一些缺陷。 `getchar 的简单实现如下所示:

    #include <stdio.h>
    
    int main (void) {
    
        char StudentName[40] = {0}; /* char array   */
        int letter = 0;             /* int value    */
        size_t idx = 0;             /* array index  */
    
        printf ("\nEnter StudentName (until ':'): ");   /* always prompt */
    
        /* read input until ':' (or end-of-line or end-of-input) */
        while ((letter = getchar()) != ':' && letter != '\n' && letter != EOF) {
            StudentName[idx++] = letter;
    
            if (idx + 1 == 40) break;  /* prevent writing beyond array */
        }
    
        StudentName[idx] = 0;   /* nul-terminate string */
    
        printf ("\nYou entered: %s\n\n", StudentName);
    
        return 0;
    }
    

    注意:您要检查您的 sentinel 字符 ':',但您还必须检查 行尾 (换行符'\n')和输入结束EOF,通常是-1)。如果您将文件或其他内存块传递给您的代码,并且您未能检查换行符和EOF,如果您的输入中没有':',您的代码将继续读取您的输入之外的内容。 (直到发生不好的事情阻止它......)同样,您需要验证存储在数组中的字符数不超过40 - 1(为nul-terminating 字符留出空间)。只需进行简单的索引检查或检查存储的字符数即可。

    虽然您可以随意使用数组索引来用字符填充数组,但这是(许多)情况之一,您通常希望将指针分配到数组的开头,然后简单地使用指针来填充您的大批。它本质上是一个“最适合情况”的问题,这意味着两者都不比另一个更对/错,但是熟悉将指针向下移动是 C 中字符串/字符处理的基础。下面是一个使用指针。

    #include <stdio.h>
    
    int main (void) {
    
        char StudentName[40] = {0}; /* char array   */
        char *p = StudentName;      /* pointer      */
        int c = 0;                  /* int value    */
    
        printf ("\nEnter StudentName (until ':'): ");   /* always prompt */
    
        /* read input until ':' (or end-of-line or end-of-input) */
        while ((c = getchar()) != ':' && c != '\n' && c != EOF) {
            *p++ = c;
    
            if (p - StudentName + 1 == 40) break;  /* prevent writing beyond array */
        }
    
        *p = 0;   /* nul-terminate string */
    
        printf ("\nYou entered: %s\n\n", StudentName);
    
        return 0;
    }
    

    编译

    gcc -Wall -Wextra -O3 -o bin/studentname studentname.c
    

    (将-O3 优化替换为-g 以生成带有gcc 的调试符号)

    使用示例

    $ ./bin/studentname
    
    Enter StudentName (until ':'): John Q. Smith:Age 21:Weight 180
    
    You entered: John Q. Smith
    

    或将输入重定向到您的程序:

    $ printf "John Q. Smith:Age 21:Weight 180\n" | ./bin/studentname2
    
    Enter StudentName (until ':'):
    You entered: John Q. Smith
    

    注意: 这只是一个小问题,但如果您打算接受用户输入,提示用户。否则,用户只能看着闪烁的光标,想知道程序是否挂起。显然你不会在从文件中读取,但是当要求输入时,prompt

    如果您还有其他问题,请告诉我。

    【讨论】:

    • 很多好主意!次要:idx + 1 == 40 --> idx + 1 == sizeof(StudentName)
    • 你让我明白了,但40 是有意加强StudentName[40] 相关性,但使用sizeof(StudentName) 会更易于维护。如果我有我的 druthers,我们会有 #define MAXC 40char StudentName[MAXC] = {0};sizeof(StudentName)...:)
    猜你喜欢
    • 2016-10-21
    • 2015-08-04
    • 2014-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多