簡體   English   中英

返回指向字符串數組C的指針

[英]Return pointer to array of strings C

我正在嘗試返回從文件中獲取的字符串數組。 文件看起來像這樣(第一行是單詞數,每行都是單詞)。 當函數結束時,我會在主要部分得到一些奇怪的輸出。 我想返回指向字符串數組的指針。 請注意,使用打印的代碼的某些部分用於檢查我的程序。

這是分配內存的函數:

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

在這里,您必須使用二維數組(用char **代替char * )。 由於返回rijeci數組,因此必須將rijeci聲明為char **rijeci;

  1. 這兩個函數的返回類型也應為char **
  2. rijeci + i更改為rijeci[i]
  3. 正確的代碼縮進。

試試這個修改后的代碼。 這將起作用:-

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

你知道數組字符串的定義嗎?

我會按照2011年C標准的要求將它們提供給您:

數組類型描述具有特定成員對象類型(稱為元素類型)的連續分配的非空對象集。 [...]

字符串是連續的字符序列,以第一個空字符結尾並包括第一個空字符。 [...]

因此, 數組是從完整對象類型派生的類型,但是字符串不是類型而是數據結構。


你非常高興。 您確定要強迫編譯器無理由地相信您是一個好習慣嗎? 還建議使用sizeof expr不是sizeof (TYPE) ,因為一開始很難出錯,或者在以后進行重構時不同步。
考慮閱讀“ 我是否強制轉換malloc的結果? ”。

您遇到的第一個問題在這里:

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 因此,當您讀取第一行時, i0 ,但是在復制它之前先對其進行了遞增,因此您的數組未設置其第一次出現的狀態,並且您將最后一個字寫入未分配的內存中。

這部分應該是:

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
    }

如果要返回大小為20的char數組的指針,則必須聲明該函數,如下所示:

char (*generisiProstor(int n))[20]
{
    return malloc(n*sizeof(char[20]));
}

持有指向數組的指針的變量聲明為:

char (*rijeci)[20];

rijeci[i]的類型為char[20] ,您可以在其中編寫字符串。

您正在分配正確的內存量,但是您需要更改使用方式。 malloc()只能返回一個“平面”字符數組,因此generisiProstor()的返回值是指向整個數組中第一個字符的簡單指針。

最初起作用的原因是每個字符串都會覆蓋前一個字符串的尾端,因此當您在讀入循環中執行打印輸出時,它們將正確顯示。 但是即使如此,您rijeci數組的有效載荷也已完全損壞。

一種可能的解決方案是使用結構來保存您的文字:

struct Rijec
{
    char rijec[20];
};

然后將generisiProstor(int n)更改為:

struct Rijeci *generisiProstor(int n)
{
    return malloc(n * sizeof(struct Rijec)); 
}

請注意,在C中不需要強制轉換,實際上應避免使用

然后,您需要將ucitajRijeci()的頂部更改為如下所示:

struct Rijec *ucitajRijeci(int n)
{
    struct Rijec *rijeci;
    ...

並且在所有使用rijeci + i情況下,我都將rijeci + i更改為rijeci[i].rijec

最終結果是,當您使用i索引rijeci數組中的單詞時,偏移量現在是正確的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM