此程序检查指向char **s
的指针数组中的单词(应首先加载)是否与函数fun
中的单词相同。由于某些原因,我无法在main
函数中正确加载单词,而且我也不知道为什么。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int fun(char **s,int j)
{
int i, num=0;
for(i=0;i<j;i++)
{
if(strcmp(s[i],"first")==0)
num++;
if(strcmp(s[i],"second")==0)
num++;
}
if(num==j)
return 1;
else
return 0;
}
int main(int argc,char *argv[])
{
char **s=(char**)malloc(20*sizeof(char*)); // alloc
char ss[20];
int i=0,ret;
while(1) // while string 'ss' is different from string "stop"
{
scanf("%s",ss);
if(strcmp(ss,"stop")==0)
break;
else
{ s[i]=ss; // if ss is different from "stop"
i++;
}
}
ret=fun(s,i); // returns 1 if words are the same as words in function fun
if(ret)
printf("Matching\n");
else
printf("Doesn't matches\n");
for(int t=0;t<i;t++)
free(s[i]);
free(s);
}
答案 0 :(得分:0)
char **s=(char**)malloc(20*sizeof(char*)); // alloc
这为20个指向char
的指针腾出了空间。实际存储char
的空间不大。
s[i]=ss; // if ss is different from "stop"
在循环中执行此操作只会导致指向char
的相同基础序列的一堆指针。您需要使用循环或类似strncpy
的函数来实际复制char
。
for(int t=0;t<i;t++)
free(s[i]);
这应该是一个明显的错误迹象,因为与此malloc
没有对应的free
。 (您只有malloc
与此下方的free(s);
相对应。)
答案 1 :(得分:0)
按照您的所有说明,我使用功能strcpy
解决了可能有相同问题的人:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int fun(char **s,int j)
{
int i;
int num=0,numm=0;
for(i=0;i<j;i++)
{
if(strcmp(s[i],"first")==0)
num=1;
if(strcmp(s[i],"second")==0)
numm=1;
}
if(num!=0 && numm!=0)
return 1;
else
return 0;
}
int main(int argc,char *argv[])
{
char **s; // pointer to pointer to char
char ss[20];
int i=0,ret; // i-number of words we entered
scanf("%s",ss);
if(strcmp(ss,"stop")!=0)
{
s=(char**)malloc(1*sizeof(char*));
s[i]=malloc(20*sizeof(char));
strcpy(s[i],ss);
i++;
}
while(1) // while string 'ss' is different from string "stop"
{
scanf("%s",ss);
if(strcmp(ss,"stop")!=0)
{
s=(char**)realloc(s,(i+1)*sizeof(char*));
s[i]=malloc(20*sizeof(char));
strcpy(s[i],ss);
i++;
}
else
break;
}
ret=fun(s,i); // returns 1 if words are the same as words in function fun
if(ret)
printf("\nMatching\n");
else
printf("\nDoesn't matches\n");
for(int t=0;t<i;t++)
free(s[i]);
free(s);
}
答案 2 :(得分:0)
简单的解决方案,如果有,请使用strdup
您的问题是您只分配了20
指针。您分配的指针是未初始化的,它们本身也不指向任何有效的存储。为了在每个s[i]
指针处存储字符串,您必须分配足以存储ss
(strlen(ss) + 1
个字符)的存储空间,然后将ss
复制到分配的新内存块中。如果您拥有strdup
函数,该函数既可以为您分配又可以为您复制,但是由于已分配,因此您需要验证分配成功,例如
#define NPTR 20 /* if you need a constant, #define one (or more) */
int main (int argc, char *argv[])
{
char **s = NULL; /* initialize all variables */
char ss[20] = "";
int i = 0,
ret = 0;
s = malloc (NPTR * sizeof *s); /* allocate NPTR pointers to char */
if (s == NULL) { /* validate EVERY allocation */
perror ("malloc-s");
return 1;
}
/* fill up to NPTR pointers with strings read from stdin */
while (i < NPTR && scanf ("%19s", ss) == 1) {
/* compare for stop */
if (strcmp (ss, "stop") == 0)
break;
/* strdup will allocate for s[i] and copy ss */
s[i] = strdup (ss);
if (s[i] == NULL) { /* it allocates -> you must validate */
perror ("strdup-s[i]");
break;
}
i++;
}
}
(注意:您必须通过在ss
调用中加入 filed width 修饰符来保护scanf
的数组边界,例如{{ 1}})
如果您没有scanf ("%19s", ss)
,只需strdup
和malloc
(或更好的strcpy
)
在没有memcpy
的情况下,您只需获取strdup
中字符串的长度,分配ss
个字符,并将新内存块的起始地址分配给length+1
,然后将s[i]
复制到新的内存块中。上面的唯一更改是:
ss
(注意:,您已经用 ...
/* fill up to NPTR pointers with strings read from stdin */
while (i < NPTR && scanf ("%19s", ss) == 1) {
size_t len = 0;
/* compare for stop */
if (strcmp (ss, "stop") == 0)
break;
len = strlen (ss); /* get length of string in ss */
s[i] = malloc (len + 1); /* allocate length + 1 chars */
if (s[i] == NULL) { /* you allocate / you validate */
perror ("malloc-s[i]");
break;
}
memcpy (s[i], ss, len + 1); /* you have length, just memcpy */
i++;
}
...
扫描了ss
以获取长度,因此不需要strlen
(再次扫描末尾),只需使用strcpy
长度的memcpy
复制 nul-termination 字符,这会更有效率)。
这两种方法均有效。然后释放已分配的内存。
+1
(也请注意::for (int j = 0; j < i; j++)
free (s[j]); /* free storage for each string */
free (s); /* free pointers */
检查可防止存储超出分配的指针数量的字符串。您不必i < NPTR
停下来,而只需i == NPTR
指针的数量,然后继续。一般的方法是跟踪已分配的指针的数量,当达到极限时,realloc
将指针的数量加倍(或将当前数量乘以{{ 1}}或其他任何方法),验证重新分配是否成功,并更新分配给新指针数量的当前数字,并继续操作直到再次达到指针限制,然后根据需要重复...)