【问题标题】:How to correctly input a string in C如何在C中正确输入字符串
【发布时间】:2014-03-08 15:33:27
【问题描述】:

我目前正在学习 C,所以我想制作一个程序,要求用户输入一个字符串并输出输入的字符数,代码编译得很好,当我只输入 1 个字符时它就可以了,但是当我输入2个或更多字符时,无论我输入多少个字符,它总是会说只有一个字符,然后崩溃。这是我的代码,我不知道出了什么问题。

int main(void)
{
    int siz;
    char i[] = "";

    printf("Enter a string.\n");
    scanf("%s", i);

    siz = sizeof(i)/sizeof(char);

    printf("%d", siz);
    getch();
    return 0;
}

我目前正在学习编程,所以如果有办法使用相同的 scanf() 函数,我会很感激,因为我还没有学会如何使用任何其他函数,并且可能不明白它是如何使用的有效。

【问题讨论】:

    标签: c arrays string input scanf


    【解决方案1】:

    请忘记scanf 的存在。您遇到的问题,虽然主要是由于您可以理解的缺乏经验造成的,但即使您有经验,也会继续困扰您 - 直到您停下来。

    原因如下:

    scanf 将读取输入,并将结果放入您提供的char 缓冲区。但是,它将不检查以确保有足够的空间。如果它需要的空间比您提供的更多,它将覆盖其他内存位置 - 通常会带来灾难性的后果。

    更安全的方法使用fgets - 这是一个与scanf 大致相同的功能,但它只会读取与您创建空间一样多的字符(或:如您说 你为它创造了空间)。

    其他观察:sizeof 只能评估大小编译时已知:原始类型(int、double 等)占用的字节数或固定数组的大小(如诠释我[100];)。它不能用于在程序期间确定大小(如果“大小”是变化的东西)。

    您的程序将如下所示:

    #include <stdio.h>
    #include <string.h>
    
    #define BUFLEN 100          // your buffer length
    
    int main(void)    // <<< for correctness, include 'void'
    {
        int siz;
        char i[BUFLEN];    // <<< now you have space for a 99 character string plus the '\0'
    
        printf("Enter a string.\n");
        fgets(i, BUFLEN, stdin);   // read the input, copy the first BUFLEN characters to i
    
        siz = sizeof(i)/sizeof(char);  // it turns out that this will give you the answer BUFLEN
                                       // probably not what you wanted. 'sizeof' gives size of array in
                                       // this case, not size of string
                                       // also not
    
        siz = strlen(i) - 1;           // strlen is a function that is declared in string.h
                                       // it produces the string length
                                       // subtract 1 if you don't want to count \n
        printf("The string length is %d\n", siz);  // don't just print the number, say what it is
                                                   // and end with a newline: \n
        printf("hit <return> to exit program\n");    // tell user what to do next!
        getc(stdin);
        return 0;
    }
    

    我希望这会有所帮助。

    更新您提出了合理的后续问题:“我怎么知道字符串太长”。

    请参阅此代码 sn-p 以获得灵感:

    #include <stdio.h>
    #include <string.h>
    
    #define N 50
    
    int main(void) {
      char a[N];
      char *b;
    
      printf("enter a string:\n");
    
      b = fgets(a, N, stdin);
    
      if(b == NULL) {
        printf("an error occurred reading input!\n"); // can't think how this would happen...
        return 0;
      }
    
      if (strlen(a) == N-1 && a[N-2] != '\n') {       // used all space, didn't get to end of line
        printf("string is too long!\n");
      }
      else {
        printf("The string is %s which is %d characters long\n", a, strlen(a)-1); // all went according to plan
      }
    
    }
    

    请记住,当您有 N 个字符的空间时,最后一个字符(在位置 N-1)必须是 '\0',并且由于 fgets 包含 '\n',因此您可以输入的最大字符串实际上是 N-2字符长。

    【讨论】:

    • 您可以通过包含格式说明符的宽度(比缓冲区长度小一)来限制scanf() 将读入字符串的字符数.. 尽管最好使用其他东西时间。
    • @Dmitri - 公平点。当缓冲区的大小是可变的时,使用格式说明符会变得很棘手,所以我更喜欢更灵活的fgets。但是有可能吗。仍然 - 在我看来 scanf 应该带着三天的口粮放入救生艇并随波逐流......
    • 每个答案确实给了我一个想法,而这个是我最喜欢的一个,但是,如果用户输入的字符多于允许的字符,我该怎么办?我的意思是,我怎样才能让程序意识到它并输出警告。
    • 乐于助人。我已经更新了一个代码 sn-p,它显示了如何判断输入对于字符串缓冲区来说太大了。
    【解决方案2】:

    这一行:

    char i[] = "";
    

    相当于:

    char i[1] = {'\0'};
    

    数组i只有一个元素,缓冲区溢出导致程序崩溃。

    我建议你像这样使用fgets() 替换scanf()

    #include <stdio.h>
    #define MAX_LEN 1024
    
    int main(void)
    {
        char line[MAX_LEN];
        if (fgets(line, sizeof(line), stdin) != NULL)
            printf("%zu\n", strlen(line) - 1);
        return 0;
    }
    

    长度减少1,因为fgets() 将在末尾存储换行符。

    【讨论】:

    • 很好,strlen 将给出字符串长度,包括'\n'
    • @Floris 实际上我一开始没有抓住它:)。但是一个简单的测试给了我错误的结果,这让我想起了一些事情。
    【解决方案3】:

    问题出在这里:

    char i[] = "";
    

    您实际上是在创建一个大小为 1 的 char array,因为它设置为等于 ""

    改为使用更大尺寸的缓冲区:

    char i[128]; /* You can also malloc space if you desire. */
    scanf("%s", i);
    

    如果您想在输入字符串中包含空格,请参阅以下类似问题的链接。还有一些关于scanf 替代方案的好意见。

    How do you allow spaces to be entered using scanf?

    【讨论】:

      【解决方案4】:

      那是因为char i[] = ""; 实际上是一个单元素数组。

      C 中的字符串存储为以\0 结尾的文本(char 的值为 0)。您应该像其他人所说的那样使用更大的缓冲区,例如:

      char i[100];
      scanf("%s", i);
      

      那么,在计算这个字符串的长度时,你需要搜索\0这个字符。

      int length = 0;
      while (i[length] != '\0')
      {
          length++;
      }
      

      运行此代码后,length 包含指定输入的长度。

      【讨论】:

        【解决方案5】:

        您需要分配用于放置输入数据的空间。在你的程序中,你可以像这样分配空间:

        char i[] = "                                     ";
        

        没关系。但是,使用malloc 更好。查看手册页。

        【讨论】:

        • char i[] = " ... " 方法的问题在于,数组到底有多大并不是很明显。最好只指定大小,例如char i[257] = {0};。动态分配并非总是更好...
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-24
        • 2016-06-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多