我在C编码阵列功能方面相对较新。经过多次尝试,我决定投降并寻求帮助。
我希望用户输入单词并将它们存储到2d数组中。问题是它打印的是单词,但也打印出随机字符。
#include "mp1_lib.h"
void get_words(int n, char words[][16])
{
char c = ' ';
char check;
for(int x=0; x <= n; x++)
{
for(int y=0; y < 16; y++)
{
c = getchar();
check = c;
if (check == '\n')
{
break;
}
words[x][y] = c;
}
}
}
void print_words(int n, char words[][16])
{
for(int x=1; x <= n; x++)
{
for(int y=0; y < 16; y++)
{
if (words[x][y] == '\n')
{
break;
}
putchar(words[x][y]);
}
printf("\n");
}
}
答案 0 :(得分:1)
不太熟悉c。但似乎您没有将新行字符添加到get_words
中的单词数组中。
check = c;
if (check == '\n')
{
break;
}
words[x][y] = c;
因此,当在print_words
中打印时,这将永远不会成真。
if (words[x][y] == '\n')
{
break;
}
这意味着无论发生在内存位置的是什么都将被打印出来。
答案 1 :(得分:1)
在C中,字符串是一个字符数组,其中 nul-terminatedating 字符'\0'
作为标记内容结尾的字符数组中的字符串。这就是所有字符串的功能如strlen
或printf
使用'%s'
格式说明符来打印字符串 - 知道字符串停止。
如果你没有 nul-terminate 字符数组 - 那么它不是一个字符串,它只是一个数组,你不能将un-terminate数组传递给任何期望字符串的函数 - 或者它不会知道字符串的结束位置(在printf
的情况下,只会打印出内存中出现的任何未指定的字符,直到它出现'\0'
来停止输出(或SegFaults) )。
如果你没有 nul-terminate 你的数组中的单词,那么你必须有一些方法来存储每个单词中的字符数,所以你的打印功能将知道在哪里停止打印。 (如果在16个字符的数组中有两个字母的单词,如"Hi"
,则只能从数组中打印2个字符。特别是如果它是未初始化的数组,那么你将只需为字符3-16
打印出乱码。
你的第二个问题是 - “你怎么知道你的阵列中存储了多少个单词?” - 您不会从getwords
返回值,因此除非您将函数类型更改为int
并返回存储在数组中的单词数,否则您唯一的选择是通过指向整数的指针并更新该地址的值,以便在调用函数中返回值。无论哪种方式都没问题,如果您已经返回另一个值并且需要第二种方法在调用函数(main()
此处)中显示另一个更新值,则通常只会担心通过指针使值可用。 / p>
将这些部分组合在一起,并将指向单词数量的指针传递到getwords
,以便在main()
中提供输入的单词数量(这样您就知道有多少单词print_words
必须打印),你可以做类似以下的事情:
#include <stdio.h>
#include <ctype.h>
#define MAXC 16 /* if you need constants, define them */
#define MAXW 32
void getwords (char (*words)[MAXC], int *n)
{
int col = 0; /* column count */
while (*n < MAXW) { /* while words < MAXW */
int c = getchar(); /* read char */
/* column reaches MAXC-1 or if whitespace or EOF */
if (col == MAXC - 1 || isspace(c) || c == EOF) {
if (col) { /* if col > 0 */
words[(*n)++][col] = 0; /* nul-terminate, increment n */
col = 0; /* set col to zero */
}
if (c == EOF) /* if char EOF - all done */
return;
}
else /* otherwise - just add char to word */
words[*n][col++] = c;
}
}
void prnwords (char (*words)[MAXC], int n)
{
for (int i = 0; i < n; i++) /* loop over each of n-words & print */
printf ("words[%2d]: %s\n", i, words[i]);
}
int main (void) {
char words[MAXW][MAXC] = {""}; /* intiliaze words all zero */
int nwords = 0; /* number of words zero */
getwords (words, &nwords);
prnwords (words, nwords);
return 0;
}
(注意:)在将字符读入words
数组时,您必须再次检查字符读取次数,每个字的最大字符数(MAXC
)和数字对于数组中最大字数/行数(MAXW
)的单词,以防止在数组边界外写入 - 这将在程序中调用未定义行为)
(注意:包含ctype.h
标头,以简化检查字符读取是否为空白(例如space
,{{1如果你不能使用它,那么只需使用tab
代替。)
示例使用/输出
newline
答案 2 :(得分:0)
你的单词既没有换行符(这会使你的代码打印出来的垃圾)也没有终止的NULL(这使得它们非法作为C字符串)。在破坏内循环之前至少添加words[x][y]="\n"
。或者更确切地说,在作业if
之后移动words[x][y]=c;
检查。是的,循环应该从0到n-1
。
作为旁注,您不需要变量check
:只需使用c
。
答案 3 :(得分:-1)
我尝试将空间分配为15个字符的占位符并且它有效。感谢大家! :)
#include "mp1_lib.h"
void get_words(int n, char words[][16])
{
char c = ' ';
char check;
for(int x=0; x < n; x++)
{
for(int y=0; y < 16; y++)
{
words[x][y] = ' ';
}
}
for(int x=0; x < n; x++)
{
for(int y=0; y < 16; y++)
{
c = getchar();
check = c;
if (check == '\n')
{
break;
}
words[x][y] = c;
}
}
}
void print_words(int n, char words[][16])
{
for(int x=0; x < n; x++)
{
for(int y=0; y < 16; y++)
{
putchar(words[x][y]);
}
printf("\n");
}
}