2017-01-23 183 views
0

我想在C中写一个通用的打印数组函数,并以某种方式它不能很好地处理字符串数组。 这里的主:C通用打印数组函数 - 打印字符串数组

#define LEN 20 

typedef struct 
{ 
char name[LEN]; // worker's name 
int salary; // worker's salary 
char **childArr; // array of children names 
int numChildren; // number of children 
}Worker; 

void printArray(void* arr, int size, int typeSize, void (*print)(void*)); 
void printString(void* s); 
void printWorker(void* worker); 

void main() 
{ 
// arrays of children's names 
char *chBamba[] = { "Bambale1", "Bamb2", "Bamb3", "Bambook4", "Bambookle5" }; 
char *chBisli[] = { "Bislile1", "Bischick2", "Bislile3", "Bis4"}; 
int nBamba = sizeof(chBamba)/sizeof(*chBamba); 
int nBisli = sizeof(chBisli)/sizeof(*chBisli); 
// array of workers 
Worker a[] = { {"Printf", 10, NULL, 0} , {"Bisli", 20, chBisli, nBisli}, 
{"TapooChips", 3, chBamba, nBamba}, {"Bamba", 19, chBamba, nBamba} }; 

printArray(a,sizeof(a)/sizeof(Worker),sizeof(Worker),printWorker); 

} 

而且功能:

void printArray(void* arr, int size, int typeSize, void (*print)(void*)) 
{ 
    int i; 
    for (i=0;i<size;i++) 
    { 
     print((char*)arr+i *typeSize); 
    } 
    printf("\n"); 
} 

void printString(void* s) 
{ 
    char* str = (char*)s; 
    printf("[ %s ]",*str); 
} 

void printWorker(void* worker) 
{ 
    Worker* w = (Worker*)worker; 
    printf("%s\t %d...(%d) ",w->name,w->salary,w->numChildren); 
    if (w->numChildren != 0) 
     printArray(w->childArr,w->numChildren,LEN,printString); 

    printf("\n"); 
} 

打印第二工人的数据和去“孩子”阵列,代码休息后...

任何想法为什么?我该如何解决它?

编辑此之后:printArray(w->childArr,w->numChildren,sizeof(w->childArr[0]),printString);

这个:printf("[ %s ]",str);

我现在有以下打印: img1

+0

好,'的printf(“[%s]的”,* STR);'肯定是不好,和你的编译器应该扔了一个大胖子警告信息,告诉你。 'str'是'char *',所以'* str'是'char',这对'%s'来说并不好。基本上,当你承诺给它一个指向char的指针并给它指定char时,你就骗过了'printf'。而且,不需要'char * str =(char *)s;'中的强制转换。在C中转换或从类似const的'void *'是自动的。 – WhozCraig

+0

您不使用正确的类型'size_t'进行索引。并且你什么也不施展,“Worker * w =(Worker *)worker;'=>'Worker * w = worker;' – Stargateur

+0

@Stargateur - 编译器无关紧要。 – LjTiNo

回答

1

这里这条线:

printArray(w->childArr,w->numChildren,LEN,printString); 

您传递LEN作为数组中元素的大小,这可能是大于数组元素的大小。这使得printArray中的循环不在数组边界之外,其中任何访问都是未定义的行为。

你的数组包含指向字符串的指针。您需要通过sizeof(char*)。或者,更D.R.Y方式:

printArray(w->childArr, w->numChildren, sizeof w->childArr[0], printString); 

printString功能做了错误的类型转换。您必须记住printArray将指向当前元素的指针传递到回调函数中。由于你迭代了一个char*数组,它将通过一个char**。考虑到这一点:

void printString(void *vpStr) { 
    char **pStr = vpStr; 
    printf("[ %s ]", *pstr); 
} 
+0

好吧..它解决了一半的问题......现在它打印..但不是我要求它打印......你能看看我的问题的编辑? – LjTiNo

+0

@LiTiNo - 查看我的编辑。类型擦除需要一点关注细节。 – StoryTeller

+0

我必须用char ** str =(char **)s来做; (idk为什么我的编译器不会让我没有铸造..),但它的工作原理!你太棒了! :) – LjTiNo

0

仅供参考,您使用的方法是如何传统的C.完成,但在现代的C您可以以更好的方式写这样的通用功能:安全型和不需要函数指针:

#include <stdio.h> 
#include <string.h> 

#define print_array(data, n)   \ 
    _Generic((*data),     \ 
      int: print_int,   \ 
      char: print_char)(data,n) \ 


void print_int (const int* data, size_t n) 
{ 
    for(size_t i=0; i<n; i++) 
    { 
    printf("%d ", data[i]); 
    } 
} 

void print_char (const char* data, size_t n) 
{ 
    for(size_t i=0; i<n; i++) 
    { 
    printf("%c ", data[i]); 
    } 
} 



int main (void) 
{ 
    int int_array [3] = {1, 2, 3}; 
    const char* char_array = "hello world"; 

    print_array(int_array, 3); 
    printf("\n"); 
    print_array(char_array, strlen(char_array)); 
    printf("\n"); 

}