【问题标题】:Inputting multiple lines of strings in C在C中输入多行字符串
【发布时间】:2017-05-14 03:00:12
【问题描述】:

我对编码还很陌生,目前正在学校学习 C 语言的编程课程。我们被分配了一项作业,我在第一部分遇到了一些困难。我们正在学习如何使用字符串处理库 (stdlib.h),作业的目标是从键盘输入多行文本。导师建议我们使用二维数组来做到这一点,但我有点卡住了。这是我写的代码:

int main(void) {
    char string[3][SIZE];
    int i, j;
    int c;

    printf("Enter three lines of text:\n");

    for (i = 0; i < 3; i++) {
        j = 0;
        while ((j < SIZE) && (c = getchar() != '\n')) {
            string[i][j] = c;
            j++;
        }
    }

    for (i = 0; i < 3; i++) {
        for (j = 0; j < SIZE; j++) {
            printf("%c", string[i][j]);
        }
        printf("\n");
    }

    return 0;
}

我想说明的几点是,我使用 getchar() 函数一次接收一个字符的输入,以及第二个 for 循环,我打算打印存储在每一行中的每一行文本的字符串数组。

输入是三行的任意文本字符串,例如:

Hi my name is John.\n
I am from the US\n
and I'm a student.

这是当前输出的样子:

Enter three lines of text:
rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr...

我期待的输出是:

Enter three lines of text:\n
Hi my name is John.\n
I'm from the US\n
and am a student.

任何提示或建议将不胜感激。谢谢!

【问题讨论】:

  • 逐字练习是练习的要求吗?
  • 是的!这就是我使用 getchar() 函数的原因。我的导师推荐,因为我们正在研究字符串处理库,我们尝试尽可能多地利用它,无论是否合适或效率。
  • @Sean 感谢您的澄清。 BTW string.h 是字符串处理库。 stdio.hgetchar 来自的 IO 处理库。 stdlib.h 有点像垃圾场。
  • 修复this
  • 这个c = getchar() != '\n' 不符合您的预期。

标签: c arrays string


【解决方案1】:

首先让我赞扬您从 C 开始的事实。这是最可靠的学习语言(更好的是汇编本身)-您将完全了解事物的工作原理,而您不会如果从在 C 之上编写的某种语言(如 Java 和 Python)开始。 但这是一条艰难而漫长的道路,值得。

关于代码:有很多事情要做,而且你已经做了很多有趣的错误,这些错误会在你运行它的机器上每隔一段时间重现不同的有趣的东西。

首先:要让你的代码以某种方式工作,你只需要添加括号:

    while ((j < SIZE) && ((c = getchar()) != '\n')) {

在 C 中,一切都是二进制的(或整数,取决于你如何看待它),默认绑定在右边 a op1 b op2 c op3 d.. 首先 op3 被评估 c op3 d = r1,然后你有一个 op1 b op2 r1 等等。 因此,您将 getchar() 的值与字符 '\n' 的值进行比较 - 它们不相等,因此您得到 TRUE(值 1)并将其存储在局部变量 c 中。

接下来,由于初始化数组的方式,您仍然存在一些问题:

     char string[3][SIZE];

它所做的只是将您处理地址空间的 3*SIZE*sizeof(char) 字节“委托”给标记为“字符串”的事物。但这并不能清除这些字节上以前直播(您的程序,甚至之前)的所有残余,所以如果您的程序中的 SIZE == 100 并且您曾经将信用卡存储在真实地址内存中(RAM) 映射到程序内存的那个区域,当您通过 printf 打印它时,您会看到您的信用卡 - 如果您没有覆盖这 300 个字节。

这可能有助于您查看它:

#include <stdlib.h>
#include <stdio.h>

#define SIZE 10

int main(void) {
    char string[3][SIZE];
    int i, j;
    int c;

    for(i = 0; i < 3; i++)
      for(j = 0; j < SIZE; j++){
        string[i][j] = 0;
      }
    printf("Enter three lines of text:\n");

    for (i = 0; i < 3; i++) {
        j = 0;
        while ((j < SIZE) && ((c = getchar()) != '\n')) {
            string[i][j] = c;
            j++;
        }
    }

    for (i = 0; i < 3; i++) {
        for (j = 0; j < SIZE; j++) {
            printf("%c", string[i][j]);
        }
        printf("\n");
    }

    return 0;
}

还要注意 getchar() 可能在输入和换行时表现不佳 - 这取决于您是否在将输入发送到您的程序之前在 enter(newline) 上进行控制台缓冲输入。更多这里How to avoid press enter with any getchar()

【讨论】:

    【解决方案2】:

    注意:我在 OP 澄清他们必须使用 getchar 之前写了这个答案。

    要一次读取整行,请使用fgets。要一次打印整个字符串,请使用 printf%s 格式。

    #include <stdio.h>
    
    int main(void) {
        // No need to define a SIZE constant.
        // Because it's stack allocated we can its size.
        char strings[3][100];
    
        printf("Enter three lines of text:\n");
    
        for ( int i = 0; i < 3; i++) {
            // Reads one line, up to the size of `strings[i]`, from stdin.
            fgets( strings[i], sizeof(strings[i]), stdin );
        }
    
        for ( int i = 0; i < 3; i++) {
            // Print each string and its line number.
            printf("Line %d: %s\n", i, strings[i]);
        }
    
        return 0;
    }
    

    这不是读取输入的最佳模式。你会很快了解到固定的内存大小和读取输入不能很好地工作。以供将来参考,它会更像这样。

    #include <stdio.h>
    #include <string.h>
    
    int main(void) {
        // A list to store 3 strings, but no memory for the strings themselves.
        char *strings[3];
    
        printf("Enter three lines of text:\n");
    
        // A line buffer that's sufficiently large.
        // This will be reused.
        char line[4096];
        for ( int i = 0; i < 3; i++) {
            // Read into the large line buffer.
            fgets( line, sizeof(line), stdin );
    
            // Copy the string into a buffer that's just big enough.
            strings[i] = strdup( line );
        }
    
        for ( int i = 0; i < 3; i++) {
            printf("Line %d: %s\n", i, strings[i]);
        }
    
        return 0;
    }
    

    这会分配一个大的行缓冲区来进行读取,然后将使用strdup 读取的内容复制到大小合适的内存中。这可以让您读取甚至很长的输入行,而不会浪费大量内存(如果它们很短)。

    请注意,strdup() 不是 C 标准库的一部分,但它是 POSIX 规范的一部分。任何主要的编译器都会有它,而且很容易编写你自己的。

    【讨论】:

      猜你喜欢
      • 2011-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多