将字符串作为二维char数组

时间:2018-06-29 10:54:25

标签: c string loops multidimensional-array char

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

输入

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

谁能告诉我我要去哪里错了?

4 个答案:

答案 0 :(得分:1)

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

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

将值4赋予m,输出为:

2 4
ab
cd
ab
cd

在使用scanf()进行字符串输入时,最好添加小于输入缓冲区长度1的最大字符修饰符检查。因此,如果输入缓冲区的大小为4,则可以

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

这样,scanf()将在3中读取不超过a[i]个字符,并将\0添加到a[i]的第四位置。请注意,它不会丢弃输入流中的剩余输入,并且连续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()?

答案 1 :(得分:0)

C中的所有字符串都必须以空字符\0结尾,print知道这一点,并在该符号之前打印所有字符。为避免出现此问题,您应该使所有字符串比计划插入的字符串长1个字符,并在开始时将其填充为0(0是\0的整数值)。

答案 2 :(得分:0)

考虑使用fgets捕获输入。在这种情况下,很难将scanf限制为m允许的字符数。 fgets会解决这个问题,但请记住,换行符是fgets所计数的字符之一。

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

int main( void)
{
    int i = 0;
    size_t n = 0, m = 0;
    int scanned = 0;
    char values[100] = "";

    do {
        printf ( "enter two values as x y ( x > 0 and y > 2)\n");
        if ( fgets ( values, sizeof values, stdin)) {
            scanned = sscanf ( values, "%zu%zu", &n ,&m);
        }
        else {
            fprintf ( stderr, "problem fgets\n");
            return 0;
        }
    } while ( scanned != 2 || n < 1 || m < 3);

    char a[n][m + 2];//+2 for newline and '\0'

    i = 0;
    do {
        printf ( "enter string %zu\n", i + 1);
        if ( !fgets ( a[i], m + 2, stdin)) {
            fprintf ( stderr, "problem fgets\n");
            return 0;
        }
        if ( !strchr ( a[i], '\n')) {//string does not have newline
            printf ( "enter no more than %zu characters\n", m);
            while ( !strchr ( a[i], '\n')) {//call until newline is found to clear input
                if ( !fgets ( a[i], m + 2, stdin)) {
                    fprintf ( stderr, "\nfgets problem\n");
                    return 0;
                }
            }
        }
        else {
            i++;
        }
    } while ( i < n);

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

答案 3 :(得分:0)

您正在使用char的2D数组:

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;
}