【问题标题】:Taking strings as a 2-D char array将字符串作为二维字符数组
【发布时间】:2018-12-08 13:16:09
【问题描述】:

我想要一个代码,以便我一个接一个地输入一些字符串(通过按回车键)并显示它。 例如;

输入

abc
def

输出

abc    
def

我也希望这个输入在一个数组中,这样我就可以选择任何字符

随时从数组中获取。例如:s[1][1] 给出 'e'。

我已经为这个问题写了一个代码。

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

int main()
{
    int i, j, n, m;

    scanf("%d%d", &n, &m);
    char a[n][m];

    for (i = 0; i<n; i++)
        scanf("%s", a[i]);


    for (i = 0; i<n; i++) {
        printf("%s", a[i]);
        printf("\n");
    }
}

但是对于这段代码,我的输入/输出是这样的:

输入

ab
cd

输出

abcd
cd

谁能告诉我哪里出错了?

【问题讨论】:

  • 您所显示的输入缺少nm 的输入值。显示您给nm 的输入值。
  • 使用 gcc 和 c99+ 时,可变长度数组数组 char a[n][m]; 没有问题,但请注意,并非所有编译器都支持它们。处理完基础知识后,查看声明/分配多个指针(例如char **a = malloc (n * sizeof *a);),使用足够大的缓冲区读取(例如char buf[1024] = ""; scanf("%s", buf);(检查返回)),然后为每个字符串分配存储空间(例如@987654334 @)。这为您的字符串提供了分配的存储空间,同时提供了对字符串索引的访问,a[1][1]

标签: c string loops multidimensional-array char


【解决方案1】:

您没有在问题中显示nm 的输入值。但从显示的输入和输出字符串来看,char 数组a[i] 似乎没有足够的空间来终止空字符\0。当您提供格式说明符%s 时,scanf() 会自动在存储序列的末尾添加一个终止空字符。我用2 输入nm 尝试了你的代码,我得到了你得到的输出:

$ ./a.out
2 2
ab
cd
abcd
cd

将值4 赋予m,输出为:

2 4
ab
cd
ab
cd

当使用scanf() 进行字符串输入时,最好添加检查最大字符修饰符1 是否小于输入缓冲区的长度。所以,如果输入缓冲区的大小是4 那么你可以这样做

scanf("%3s",a[i]);

这样,scanf() 将在a[i] 中读取不超过3 字符,并将在a[i] 的第四个位置添加\0。请注意,它不会丢弃输入流中剩余的输入,它们将被连续的scanf() 调用消耗。

如果您想删除 scanf 未使用的额外输入,一种方法是使用循环读取并丢弃额外输入,如下所示:

int c;
while((c = getchar()) != '\n' && c != EOF)
    /* discard the character */;

你可以在scanf()从输入流中读取数据后添加,如下:

    for(i=0; i<n; i++) {
        scanf("%3s", a[i]);  // assuming the size of a[i] is 4
        int c;
        while((c = getchar()) != '\n' && c != EOF)  // <=== This loop read the extra input characters and discard them
            /* discard the character */;
    }

这适用于不包含任何空白字符的输入。如果您的输入包含任何空白字符,则它的行为可能与预期不同。因此,我建议您阅读有关 fgets() 的内容,它可以让您更好地控制字符串输入。

检查这个:fgets
还有这个:How to read from stdin with fgets()?

【讨论】:

    【解决方案2】:

    您正在使用char 的二维数组:

    char a[n][m];
    

    但请记住,第二个索引的值应该比您希望它为 \0 字节留出空间的字符串长度长 1 个字符。 (所有 C 字符串必须以 null 结尾)

    这意味着char a[n][m]; 最多可以包含n 字符串,每个字符串的最大长度为m-1 字节。

    char exampleStr[] = {"char count"}; //for example contains 11 characters (not 10)
    
    |c|h|a|r| |c|o|u|n|t|\0|  //note nul char is appended
    

    在循环中读取用户输入时的另一个常见问题是无法删除任何不需要的换行符,这可能导致循环表现不佳。以下是如何读取用户指定数量的字符串(使用 fgets() 而不是 scanf() )的示例,每个字符串都有用户指定的长度:(同时在过程中删除不需要的换行符(\n))

    为了便于阅读,以下示例将nm 替换为linesmaxLen

    int main(void)
    {
        int lines, maxLen, i=0;
    
        printf("Enter number of lines:");
        scanf(" %d", &lines);
        printf("Enter maxLen line length:");
        scanf(" %d", &maxLen);
    
        char line[lines][maxLen+2]; //+2 to allow for trailing newline and null
    
        fgets(line[i], maxLen, stdin);//consume anything left in stdout
        printf("Enter up to %d characters and hit return:\n%d) ", maxLen, i+1);
        for(i=0;i<(lines);i++)
        {
            fgets(line[i], maxLen, stdin);
            line[i][strcspn(line[i], "\n")] = 0; // clear newline
            printf("Enter up to %d characters and hit return:\n%d) ", maxLen, i+1);
        }
    
        return 0;
    }
    

    【讨论】:

    • 额外的line[i][strcspn(line[i], "\n")] = 0 是无用的,因为%s 转换格式读取的是单词,而不是行。如果您使用fgets() 读取行(确实是一种更安全的方法),这将很有用,但您需要将行定义为char line[lines][maxLen+2]; 以允许尾随换行符和空终止符。
    • @chqrlie - 很好的反馈。中编辑的建议。
    【解决方案3】:

    C 中的所有字符串都必须以空字符 \0 结尾,print 知道这一点并打印所有字符 UP TO 该符号。您应该使所有字符串的长度比您计划放入其中的单词长 1 个字符,并在开始时用 0 填充它们(0 是 \0 的整数值)以避免此问题。

    【讨论】:

    • 如果我尝试这样做,其他字符串的输出也会停止,例如: Input abc def If I make s[3]='\0';输出 abc ..
    • 什么是s[3],你的意思是a[i][3],一般应该是a[i][m-1]
    • scanf("%d%d",&n,&m);字符 [n][m]; for(i=0;i
    • @AyazSImran - " %c" 中的空白会消耗换行符,这会导致循环行为不佳。还有其他方法可以做到这一点。 (见上文)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-23
    • 2016-02-22
    相关资源
    最近更新 更多