扫描2d字符数组

时间:2016-06-12 22:11:45

标签: c arrays

此代码不扫描整个数组。它在中间打破

# include<stdio.h>
# include<stdlib.h>
int** create(int m)
{
  char **a;
  int i;
  a=(char**)malloc(sizeof(char*)*m);
  for(i=0; i<m; i++)
    *(a+i)=(char*)malloc(sizeof(char)*m);
  return a;
}
int main()
{
  int i,j,n;
  char **a;
  scanf("%d",&n);
  a = create(n);
  for(i=0;i<n;i++)
    for(j=0;j<n;j++)
      scanf("%c",*(a+i)+j);

  printf("Output is \n");
  for(i=0;i<4;i++)
    for(j=0;j<4;j++)
      printf("%c",*(*(a+i)+j));
  return 0;
}

给出的输入是n = 4 它扫描两行,然后打印回两行...... 这是输出的屏幕截图 Output ScreenShot

3 个答案:

答案 0 :(得分:1)

您的代码中存在大量问题。当我们来到他们面前时,我们将解决他们。首先,虽然您可以在单个函数中为m指针和m个指针分配存储空间,但它会使该函数在使用中非常有限。最好使用一个分配给定字节数的函数,并为您进行错误检查(如果你愿意,可以检查错误malloc),例如

void *create (size_t s)
{
    void *memptr = calloc (1, s);
    if (!memptr) {
        fprintf (stderr, "create() error: virtual memory exhausted.\n");
        exit (EXIT_FAILURE);
    }

    return memptr;
}

注意: calloc用于初始化所有字符和指针0, NULL,以防止在未输入所有字符的情况下从未初始化的值读取。)

您的变量类型int很好,但不是最优的,因为malloc期望size_t(并且因为数组索引不能为负数,所以对所有人来说更有意义)

    size_t i, j, n = 0;
    char **a = NULL;

您必须验证每次scanf的使用,否则,您无法知道您的代码是否正在从此处开始处理垃圾。始终,始终验证用户输入。此外,在用户按 [Enter] 后,您将在输入缓冲区'\n')中留下stdin在为第一个字符调用scanf之前进行说明。 (字符输入的更好选择是getchar())。您可以使用'*' 分配抑制运算符来scanf read&amp;丢弃尾随'\n'。 e.g。

    printf ("\n enter number of pointers to create: ");
    if (scanf (" %zu%*c", &n) != 1) { /* strip \n from input buf */
        fprintf (stderr, "error: invalid unput.\n");
        return 1;
    }

接下来,由于create是一个有用的分配函数,它将为每个调用分配一个内存块,因此您只需为所需的每个内存块调用create。 e.g。

    a = create (n * sizeof *a);   /* allocate mem for n pointers */
    for (i = 0; i < n; i++)
        a[i] = create (n);        /* allocate n chars per-ponter */

阅读您的数据会带来您在上面'\n'时遇到的同样问题。您需要一些方法对其进行说明并将其删除,或scanf ("%c", ...)将很乐意接受'\n'作为您的下一个输入。您可以在一行中输入所有字符,或者您可以实际检查是否存在'\n'并忽略它,如下所示:

    printf (" enter (%zu x %zu) chars ('\\n' ignored)\n", n, n);
    for (i = 0; i < n; i++) {     /* read (n x n) chars into 'a' */
        int c;
        for (j = 0; j < n && (c = getchar()) != EOF;) {
            if (c != '\n')        /* if c is not '\n' add to 'a' */
                *(*(a + i) + j++) = c;
        }
        if (c == EOF) break;      /* bail if EOF encountered */
    }

最后,在你动态分配内存的任何代码中,你有2个职责关于分配的任何内存块:(1)总是保留一个指向起始地址的指针对于内存块,(2)当不再需要时,它可以释放。完成已分配的内存后,free。 e.g。

    for (i = 0; i < n; i++)       /* free all allocated memory */
        free (*(a + i));
    free (a);

    return 0;
}

将拼图的所有部分组合在一起,您可以编写类似于以下内容的代码:

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

void *create (size_t s)
{
    void *memptr = calloc (1, s);
    if (!memptr) {
        fprintf (stderr, "create() error: virtual memory exhausted.\n");
        exit (EXIT_FAILURE);
    }

    return memptr;
}

int main (void ) {

    size_t i, j, n = 0;
    char **a = NULL;

    printf ("\n enter number of pointers to create: ");
    if (scanf (" %zu%*c", &n) != 1) { /* strip \n from input buf */
        fprintf (stderr, "error: invalid unput.\n");
        return 1;
    }

    a = create (n * sizeof *a);   /* allocate mem for n pointers */
    for (i = 0; i < n; i++)
        a[i] = create (n);        /* allocate n chars per-ponter */

    printf (" enter (%zu x %zu) chars ('\\n' ignored)\n", n, n);
    for (i = 0; i < n; i++) {     /* read (n x n) chars into 'a' */
        int c;
        for (j = 0; j < n && (c = getchar()) != EOF;) {
            if (c != '\n')        /* if c is not '\n' add to 'a' */
                *(*(a + i) + j++) = c;
        }
        if (c == EOF) break;
    }

    printf ("\n output is \n");
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++)
            putchar (*(*(a + i) + j));
        putchar ('\n');
    }

    for (i = 0; i < n; i++)       /* free all allocated memory */
        free (*(a + i));
    free (a);

    return 0;
}

示例使用/输出

将所有字符输入为单行输入

$ ./bin/create

 enter number of pointers to create: 4
 enter (4 x 4) chars ('\n' ignored)
catsdogsmiceflea

 output is
cats
dogs
mice
flea

每行输入n个字符

$ ./bin/create

 enter number of pointers to create: 4
 enter (4 x 4) chars ('\n' ignored)
cats
dogs
mice
flea

 output is
cats
dogs
mice
flea

内存使用/错误检查

必须使用内存错误检查程序,以确保您没有在已分配的内存块之外/之外写入,尝试读取或基于未初始化的值跳转,最后确认您已拥有释放了你分配的所有内存。

$ valgrind ./bin/create
==7034== Memcheck, a memory error detector
==7034== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==7034== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==7034== Command: ./bin/create
==7034==

 enter number of pointers to create: 4
 enter (4 x 4) chars ('\n' ignored)
cats
dogs
mice
flea

 output is
cats
dogs
mice
flea
==7034==
==7034== HEAP SUMMARY:
==7034==     in use at exit: 0 bytes in 0 blocks
==7034==   total heap usage: 5 allocs, 5 frees, 48 bytes allocated
==7034==
==7034== All heap blocks were freed -- no leaks are possible
==7034==
==7034== For counts of detected and suppressed errors, rerun with: -v
==7034== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1)

始终确认释放所有堆块 - 不可能泄漏并且同样重要错误摘要:0个上下文中的0个错误

查看答案,如果您有任何问题,请告诉我。

答案 1 :(得分:0)

  scanf("%c",*(a+i)+j);

i为1且j为2时,此访问哪个元素?

i为2且j为1时呢?

答案 2 :(得分:-1)

a是一个char并且不能添加到一个整数,即使它包含一个数字,所以你必须将它转换为一个整数来使用+ i,这样做你可以使用atoi()函数并包含string.h库。

atoi()接受一个字符串作为输入,但如果字符串包含字符串必须包含数字的字符,则不能正常工作。

    #include <string.h>
    #include <stdio.h>
    int main()
    {
        char a;
        int x;
        a='4';
        x=atoi(a);//now you can use x to add it to an integer  
   }

因为bob说a是一个char而且函数的返回是int所以你不能使用return a;