在C中输入多行字符串

时间:2017-05-14 03:00:12

标签: c arrays string

我对编码很新,目前正在学校和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.

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

2 个答案:

答案 0 :(得分:1)

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

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

#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规范的一部分。任何主要的编译器都会拥有它,并且编写自己的编译器很容易。

答案 1 :(得分:1)

首先让我赞扬你用C语言开始学习的事实。这是最难学的语言(更好的只是装配本身) - 你将完全理解事物的运作方式,你不会如果从一些基于C语言编写的语言(如Java和Python)开始。 但这是一条艰难而漫长的道路,值得这样做。

关于代码:有很多事情要做,你已经制作了很多有趣的错误,每隔一段时间就可以重现不同的有趣事物并运行它。

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

UICollectionView

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

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

lazy var collectionView: UICollectionView = {
    let layout = UICollectionViewFlowLayout()
    layout.minimumLineSpacing = 0
    layout.headerReferenceSize = .zero
    layout.sectionInset = .zero
    let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
    cv.backgroundColor = .green
    cv.dataSource = self
    cv.delegate = self
    cv.contentInset = .zero
    return cv
}()

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

这可以帮助您查看它:

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

还要注意getchar()在输入和换行时可能会表现糟糕 - 这取决于你是否在输入(换行符)之前将缓冲区输入控制台输入到你的程序之前。更多How to avoid press enter with any getchar()