c - C 中的数组地址有问题?
问题描述
我创建了一个动态数组名称 listProduct,现在我想从文件中读取数据并插入到这个数组中。但是我在解析数组时遇到了一些麻烦,我知道我解析了错误的地址:(但我无法解决这个问题。有人可以帮助我(我花了 3 个小时,但没有用)。谢谢全部
在主()
int main(int argc, char** argv) {
struct Product* listProduct = (struct Product*) malloc(sizeof(struct Product) * 1);
printf("address of listProduct in main: %d \n", &listProduct);
int length = 0;
char fileName[] = "products.txt";
length = readDataFromFile(&listProduct,length,fileName);
printf("address of listProduct in main after insert \n: %d \n", &listProduct);
printf("length in main %d \n", length);
printf("start for in main \n");
int i;
for(i =0; i < length; i++){
printf("%s \n", listProduct[i].tenSanPham);
}
printf("end for in main \n");
return 0;
}
在 readFile 函数中
int readDataFromFile(struct Product* listProduct,int length, char fileName[]){
printf("address of listProduct in readData: %d \n", (*listProduct));
FILE *fp;
char buff[1024];
struct Product product;
fp = fopen(fileName, "r");
while(fgets(buff, 255, (FILE*)fp) != NULL){
product = convertStringToProduct(buff);
printf("IN readData: %s \n", product.tenSanPham);
insertProduct(product, &(*listProduct), length);
length++;
}
fclose(fp);
int i ;
printf("\n\ncheck value in listProduct after insert\n");
for(i = 0; i < length; i++){
printf("IN FOREACH readData: %s \n", listProduct[i].tenSanPham);
}
printf("read done \n");
return length;
}
在插入函数中
void insertProduct(struct Product product, struct Product** listProduct, int length)
{
printf("addres of listProduct in insert %d \n", (*listProduct));
printf("Product In Insert: %s \n", product.tenSanPham);
*listProduct = (struct Product*) realloc(listProduct, sizeof(struct Product) * (length+1));
(*listProduct)[length] = product;
printf("Get product inserted: %s length: %d \n", (*listProduct)[length].tenSanPham, length);
printf("insert done!\n");
}
安慰:
address of listProduct in main: 6487568
address of listProduct in readData: 6486368
IN readData: FOOD 1
addres of listProduct in insert 1905632
Product In Insert: FOOD 1
--------------------------------
Process exited after 0.5239 seconds with return value 3221226356
Press any key to continue . . .
解决方案
你有很多错误。通过启用编译器警告可以找到其中的一些。编译时使用-Wall -Wextra -pedantic
(gcc/clang) 或您的编译器的等效项。
首先,realloc(listProduct, ...)
应该是realloc(*listProduct, ...)
。
其次,realloc
可以返回与提供的地址不同的地址。这就是为什么insertProduct
需要一个struct Product**
. 这允许它改变调用者的指针。readDataFromFile
需要做同样的事情。参数必须是struct Product **
. 地址改变的事实不是问题。
这将顺便修复您当前遇到的许多错误。例如,&(*listProduct)
将变得正确。但是,最好写成listProduct
.
进行上述修复后,listProduct[i].tenSanPham
将需要更改为(*listProduct)[i].tenSanPham
.
%p
用于指针,而不是%d
. 他们(奇怪地)需要被强制转换void*
为 for %p
。
你不检查是否realloc
成功fopen
。
固定的:
#include <stdio.h>
#include <stdlib.h>
struct Product { ... };
typedef struct Product Product; // So we don't have to use "struct Product" everywhere.
Product convertStringToProduct(const char *s) {
...
}
void insertProduct(Product **listProductPtr, size_t *lengthPtr, Product product) {
printf("[insertProduct] Address of variable in caller: %p\n", (void*)listProductPtr);
if (*lengthPtr)
printf("[insertProduct] Address of first product: %p\n", (void*)*listProductPtr); // Same: &((*listProduct)[0])
Product *tmp = realloc(*listProductPtr, sizeof(Product) * (*lengthPtr + 1));
if (!tmp) {
// ...
}
*listProductPtr = tmp;
(*listProductPtr)[(*lengthPtr)++] = product;
printf("[insertProduct] Address of variable in caller: %p\n", (void*)listProductPtr);
if (*lengthPtr)
printf("[insertProduct] Address of first product: %p\n", (void*)*listProductPtr); // Same: &((*listProduct)[0])
}
void readDataFromFile(Product **listProductPtr, size_t *lengthPtr, const char *fileName) {
printf("[readDataFromFile] Address of variable in caller: %p\n", (void*)listProductPtr);
if (*lengthPtr)
printf("[readDataFromFile] Address of first product: %p\n", (void*)*listProductPtr); // Same: &((*listProduct)[0])
FILE *fp = fopen(fileName, "r");
if (!fp) {
// ...
}
char buff[1024];
while (fgets(buff, sizeof(buff), fp)) {
Product product = convertStringToProduct(buff);
insertProduct(listProductPtr, lengthPtr, product);
}
fclose(fp);
printf("[readDataFromFile] Address of variable in caller: %p\n", (void*)listProductPtr);
if (*lengthPtr)
printf("[readDataFromFile] Address of first product: %p\n", (void*)*listProductPtr); // Same: &((*listProduct)[0])
}
int main(void) {
Product *listProduct = NULL;
size_t length = 0;
printf("[main] Address of listProduct variable: %p\n", (void*)&listProduct);
if (length)
printf("[main] Address of first product: %p\n", (void*)listProduct); // Same: &(listProduct[0])
readDataFromFile(&listProduct, &length, "products.txt");
printf("[main] Address of listProduct variable: %p\n", (void*)&listProduct);
if (length)
printf("[main] Address of first product: %p\n", (void*)listProduct);
for (size_t i=0; i<length; ++i) {
printf("%s\n", listProduct[i].tenSanPham);
}
return 0;
}
推荐阅读
- python - 如何在 python 中使用 google/gin-config?
- asp.net-core-mvc - 在 mvc 核心中从另一个控制器调用一个控制器的操作
- python - Django Paypal IPN:仅在实时模式下的错误内容类型(它在沙箱中工作)
- javascript - 在某些文本中更改文本颜色 onclick 不起作用
- swift - 为什么将两个 UITextField 的 UIView 重用为 .leftView 会导致大量内存使用
- mysql - 将新列附加到表并使用 CSV 文件中的数据填充它
- html - Aurelia:尝试使用单个数组制作 2 个 HTML 列
- c++ - C++ 解决与遗留未命名命名空间的冲突
- python - 安装错误:在 Windows 上安装底图
- ruby-on-rails - 如何在 Rails 中使用自定义 Bulma 主题