我试图返回从文件中获取的字符串数组。文件看起来像这样(第一行是单词数,每行都是单词)。当函数结束时,我会在主要部分得到一些奇怪的输出。我想返回指向字符串数组的指针。请注意,使用打印的部分代码用于检查我的程序。
这是分配内存的函数:
char *generisiProstor(int n) {
return (char*)malloc(n*sizeof(char[20]));
}
此函数用于从rijeci.txt
提取单词,并且应返回指向包含单词的字符串数组的指针:
char* ucitajRijeci(int n) {
char i;
char *rijeci;
static const char filename[] = "rijeci.txt";
FILE *file;
file = fopen(filename, "r");
if (file != NULL)
{
char line[20];
int n;
fscanf(file, "%d", &n);
rijeci = generisiProstor(n);
if (rijeci == NULL) {
return NULL;
}
int i = -1;
fgets(line, 20, file); //skipping first line witch is integer and not needed
while (fgets(line, 20, file) != NULL)
{
printf("%s\n", line); //normal output
i++;
strcpy(rijeci + i, line);
printf("%s\n", rijeci + i); //normal expected output
}
for (i = 0; i < n; i++) {
printf("%s\n", rijeci + i); //wrong output
}
}
return rijeci;
}
主要
int main()
{
static const char filename[] = "rijeci.txt";
FILE *file;
file = fopen(filename, "r");
char *rijeci;
int i;
if (file != NULL)
{
char line[20];
int n;
fscanf(file, "%d", &n);
rijeci = ucitajRijeci(n);
printf("Here is the array: ");
for (i = 0; i < n; i++) {
printf("%s ", rijeci+i); //wrong output
}
}
return 0;
}
答案 0 :(得分:2)
在这里,您必须使用二维数组(char **
而不是char *
)。由于您要返回二维数组,因此必须将rijeci
声明为char **rijeci;
char **
。rijeci + i
更改为rijeci[i]
。尝试此修改后的代码。这将起作用:-
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* generisiProstor */
char **generisiProstor(int n)
{
char **c; // making 2-d array
c = (char **)malloc(n * sizeof(char *));
for (int i = 0; i < n; i++)
{
c[i] = (char *)malloc(20 * sizeof(char));
}
return c;
}
/* ucitajRijeci */
char **ucitajRijeci(int n)
{
char **rijeci; // change to char **
static const char filename[] = "rijeci.txt";
FILE *file;
file = fopen(filename, "r");
if (file != NULL)
{
char line[20];
int n;
fscanf(file, "%d", &n);
rijeci = generisiProstor(n);
if (rijeci == NULL)
{
return NULL;
}
int i = -1;
fgets(line, 20, file); //skipping first line witch is integer and not needed
while (fgets(line, 20, file) != NULL)
{
printf("%s\n", line); //normal output
i++;
strcpy(rijeci[i], line);
printf("%s\n", rijeci[i]); //changed to rijeci[i]
}
for (i = 0; i < n; i++)
{
printf("%s\n", rijeci[i]); //changed to rijeci[i]
}
}
return rijeci;
}
/* main() */
int main()
{
static const char filename[] = "rijeci.txt";
FILE *file;
file = fopen(filename, "r");
char **rijeci; // change to char **
int i;
if (file != NULL)
{
char line[20];
int n;
fscanf(file, "%d", &n);
rijeci = ucitajRijeci(n);
printf("Here is the array: ");
for (i = 0; i < n; i++)
{
printf("%s ", rijeci[i]); //changed to rijeci[i]
}
}
return 0;
}
答案 1 :(得分:1)
您知道 array 和 string 的定义吗?
我会按照2011年C标准的要求将它们提供给您
数组类型描述具有特定成员对象类型(称为元素类型)的连续分配的非空对象集。 […]
string 是连续的字符序列,以第一个空字符结尾并包括第一个空字符。 […]
因此, array 是从完整对象类型派生的类型,但是 string 不是类型,而是数据结构。
你非常高兴。您确定要强迫编译器无理由地相信您是一个好习惯吗?与sizeof expr
相比,sizeof (TYPE)
也更受欢迎,因为在以后重构时更容易出错或不同步。
考虑阅读“ Do I cast the result of malloc? ”。
答案 2 :(得分:0)
您遇到的第一个问题在这里:
char *generisiProstor(int n) {
return (char*)malloc(n*sizeof(char[20]));
}
您需要一个char指针数组,但是返回一个char指针或char数组。
这部分应该是:
char **generisiProstor(int n) {
return (char**)malloc(n*sizeof(char[20]));
}
char *rijeci
遇到相同的问题,您将其声明为字符串或char指针。
您应该像这样char **rijeci
声明它(在这种情况下,您可能希望它是char *(rigeci[20])
),这样它将是一个字符串数组。
如果我的代码正确无误,则此部分可能会出现另一个问题:
while (fgets(line, 20, file) != NULL)
{
printf("%s\n", line); //normal output
i++;
strcpy(rijeci + i, line);
printf("%s\n", rijeci + i); //normal expected output
}
在代码的早期,您为n
个单词分配了内存。在这里,您正在阅读该行,并将其放入line
中。因此,当您读取第一行时,i
是0
,但是在复制前先增加它,因此数组未设置其第一次出现的位置,并且将最后一个字写入未分配的内存中。
这部分应该是:
while (fgets(line, 20, file) != NULL)
{
printf("%s\n", line); //normal output
strcpy(rijeci + i, line);
i++
printf("%s\n", rijeci + i); //normal expected output
}
答案 3 :(得分:0)
如果要返回大小为20的char数组的指针,则必须声明该函数,如下所示:
char (*generisiProstor(int n))[20]
{
return malloc(n*sizeof(char[20]));
}
保存指向数组的指针的变量声明为:
char (*rijeci)[20];
rijeci[i]
类型为char[20]
,您可以在此处编写字符串。
答案 4 :(得分:0)
您正在分配正确的内存量,但是您需要更改使用方式。 malloc()
只能返回一个“平面”字符数组,因此,generisiProstor()
的返回值是指向整个数组中第一个字符的简单指针。
最初起作用的原因是每个字符串都会覆盖前一个字符串的尾端,因此当您在读入循环中执行打印输出时,它们将正确显示。但是,即使这样,rijeci
数组的有效负载也会在您完成读取时完全损坏。
一种可能的解决方案是使用一个结构来保存您的单词:
struct Rijec
{
char rijec[20];
};
,然后将generisiProstor(int n)
更改为:
struct Rijeci *generisiProstor(int n)
{
return malloc(n * sizeof(struct Rijec));
}
请注意,C语言并不需要should be avoided强制转换。
然后,您需要将ucitajRijeci()
的顶部更改为这样:
struct Rijec *ucitajRijeci(int n)
{
struct Rijec *rijeci;
...
,并且在所有使用rijeci + i
的情况下,都将其更改为rijeci[i].rijec
。
其最终结果是,当您使用i
为rijeci
数组中的单词建立索引时,偏移量现在将是正确的。