簡體   English   中英

通過指針C將數組連接到結構

[英]Connecting array to a structure by a pointer C

我有一個結構:

struct s 
{
    unsigned size;
    char *var;
};

以及指向結構的指針數組

for(i=0;i<rows;i++)
{
    for(j=0;j<columns;j++)
    {
        array[i][j] = (struct s*)malloc(sizeof(struct s));
        printf("Give the size to structure nr. %d: \n",i*columns+j+1);
        scanf("%d",&(array[i][j]->size));
    }
}   

以及一個返回指向隨機字符數組的指針的函數,該數組的大小由用戶選擇:

char* ChainOfCharacters(int liczba)
{
    int i;
    char *tabc = NULL;
    tabc = (char*)malloc(liczba*sizeof(char));
    if(tabc==NULL) exit(-1);

    else
    {
        char *tab=NULL;
        tab=tabc;
        for(tabc;tabc<tab+liczba;tabc++)
        {
            *tabc=rand()%(122-97)+97;
        }
    return tabc;    
    }
}

如何通過使用指向結構的指針數組將作為此函數結果的字符數組連接到structure s的指針char *var 我的代碼有什么錯誤嗎?

我試過了: array[i][j]->var=ChainOfCharacters(array[i][j]->size); 但這似乎是錯誤的,因為在嘗試通過printf檢查此字符時我輸入了錯誤的字符。 我什至不知道如何通過printf在屏幕上寫入字符數組。 我嘗試了這個printf("%c ", *(array[i][j]->var)); 但顯示完全隨機的跡象。 我將非常感謝您對我的問題的回答:)

首先,讓我們理順所發布代碼的一些問題。 size_t是數組索引和大小的正確類型,因此s結構的.size成員應具有size_t類型。 這也意味着ChainOfCharacters()函數應采用size_t類型的參數,這對printf()scanf()的調用中的格式字符串說明符有影響。

用戶可能不會在輸入提示下輸入數字,在這種情況下,將不會進行分配。 但是由於發布的代碼沒有檢查從scanf()返回的值來驗證是否進行了正確的輸入,因此代碼將在該.size字段中繼續使用不確定的值,從而導致未定義的行為。 下面的代碼對此進行了檢查,如果用戶未能在此處輸入數字,則退出並顯示一條錯誤消息,盡管可以進一步改進此輸入驗證。

請注意,使用EXIT_FAILURE宏比使用-1更好,因為它更清晰,更可移植。

ChainOfCharacters()函數不會返回字符串,而只會返回指向字符數組的指針,因此,這些字符需要一張一張地打印出來。

請注意,無需在C中malloc()的結果,最好將identifers而不是顯式類型用於sizeof運算符的操作數:這更容易出錯,並且在類型更改時更易於維護。

ChainOfCharacters()函數中分配字符的循環不必要地復雜,並且可能由於這種復雜性而包含錯誤。 當返回時, tabc指針指向已分配存儲區末尾的1。 這可以通過重寫循環以使用索引而不是指針算術來解決。 通常,在可能的情況下使用數組索引而不是指針算術更清晰,更不易出錯。 避免使用幻數: rand() % ('z' - 'a') + 'a'意圖要比rand()%(122-97)+97清晰得多(不要害怕使用一點空格)。 此外,請注意,C標准對實現可能使用的字符編碼進行了很少的限制,尤其是不需要將其限制為ASCII。 甚至不需要像EBCDIC (仍然存在於現實世界中)那樣以連續的順序對拉丁字母進行編碼。 在這里這不太可能成為問題,但是知道有一些可移植的方法來處理此問題。

要分配ChainOfCharacters()的結果,只需將指針分配給適當的array[][]字段即可:

array[i][j]->var = ChainOfCharacters(array[i][j]->size);

要打印的內容.var字段,迭代在陣列上,並且對於每個struct ,在循環對所分配的存儲的內容.var ,打印字符:

/* print characters */
for (size_t i = 0; i < rows; i++)
{
    for (size_t j = 0; j < columns; j++)
    {
        printf("array[%zu][%zu]->val: ", i, j);
        for (size_t k = 0; k < array[i][j]->size; k++) {
            putchar(array[i][j]->var[k]);
        }
        putchar('\n');
    }
}

完成所有這些操作后,您將需要記住free()分配的內存。 這是實現這些更改的完整程序。

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

struct s 
{
    size_t size;
    char *var;
};

char* ChainOfCharacters(size_t liczba);

int main(void)
{
    size_t rows = 3;
    size_t columns = 3;
    struct s *array[rows][columns];

    for (size_t i = 0; i < rows; i++)
    {
        for (size_t j = 0; j < columns; j++)
        {
            array[i][j] = malloc(sizeof *array[i][j]);
            printf("Give the size to structure nr. %zu: \n",
                   i * columns + j + 1);

            if (scanf("%zu", &(array[i][j]->size)) != 1) {
                fprintf(stderr, "Incorrect input\n");
                exit(EXIT_FAILURE);
            };
            array[i][j]->var = ChainOfCharacters(array[i][j]->size);
        }
    }

    /* print characters */
    for (size_t i = 0; i < rows; i++)
    {
        for (size_t j = 0; j < columns; j++)
        {
            printf("array[%zu][%zu]->val: ", i, j);
            for (size_t k = 0; k < array[i][j]->size; k++) {
                putchar(array[i][j]->var[k]);
            }
            putchar('\n');
        }
    }

    /* free allocated memory */
    for (size_t i = 0; i < rows; i++)
    {
        for (size_t j = 0; j < columns; j++)
        {
            free(array[i][j]->var);
            free(array[i][j]);
        }
    }

    return 0;
}

char* ChainOfCharacters(size_t liczba)
{
    char *tabc = NULL;
    tabc = malloc(sizeof *tabc * liczba);
    if (tabc == NULL) {
        exit(EXIT_FAILURE);
    } else {
        for (size_t i = 0; i < liczba; i++) {
            tabc[i] = rand() % ('z' - 'a') +'a';
        }
        return tabc;
    }
}

樣本互動:

Give the size to structure nr. 1: 
1  
Give the size to structure nr. 2: 
2
Give the size to structure nr. 3: 
3
Give the size to structure nr. 4: 
9
Give the size to structure nr. 5: 
8
Give the size to structure nr. 6: 
7
Give the size to structure nr. 7: 
4
Give the size to structure nr. 8: 
5
Give the size to structure nr. 9: 
6
array[0][0]->val: i
array[0][1]->val: lc
array[0][2]->val: psk
array[1][0]->val: lryvmcpjn
array[1][1]->val: bpbwllsr
array[1][2]->val: ehfmxrk
array[2][0]->val: ecwi
array[2][1]->val: trsgl
array[2][2]->val: rexvtj

選擇正確的類型

正如我在答案開頭所說的那樣, size_t是數組索引的正確類型,因為它是unsigned類型,可以保證能夠保存任何數組索引值。 但是, unsigned也可以,盡管unsigned intsize_t可能沒有相同的范圍。

OP代碼中的一個重要問題是.size字段是unsigned ,而在此字段中存儲輸入的scanf()語句使用d轉換說明符,該說明符應與int s一起使用。 根據該標准,不匹配的轉換說明符和參數會導致未定義的行為,包括在某些情況下似乎起作用。 但是您不能依靠未定義的行為來完成您的期望。 在發布的代碼中,應該使用%u.size字段中存儲unsigned值。 此外, ChainOfCharacters()函數被聲明為接受int類型的參數,但使用unsigned參數(來自.size )調用。 這也可能導致實現定義的行為,因為在int unsigned值可能無法表示。

可能出現此問題的另一個地方是在打印字符的循環中。 例如,考慮:

struct s 
{
    unsigned size;
    char *var;
};

/* ... */

int rows = 3;
int columns = 3;
struct s *array[rows][columns];

/* ... */

/* print characters */
for (int i = 0; i < rows; i++)
{
    for (int j = 0; j < columns; j++)
    {
        printf("array[%d][%d]->val: ", i, j);
        for (int k = 0; k < array[i][j]->size; k++) {
            putchar(array[i][j]->var[k]);
        }
        putchar('\n');
    }
}

這里, k是有signed int ,而array[i][j]->sizeunsigned int類型,因此在進行比較之前, k的值將轉換為unsigned值。 此轉換定義明確,但如果k為負數,可能會導致意外。

啟用編譯器警告將有助於在編譯時檢測到此類問題。 我總是至少使用gcc -Wall -Wextra (也使用-Wpedantic ,但是您可以不用它)。 啟用編譯器警告,並注意並修復它們。

ChainOfCharacters()函數中,您應該返回tab ,而不是tabc tab指向鏈的開頭, tabc指向鏈的結尾。

暫無
暫無

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

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