[英]Having trouble with the array address in 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
。 他們(奇怪地)需要為%p
為void*
。
您不檢查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(buf), 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;
}
更新后填寫我的代碼:
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include <stdbool.h>
struct date{
int day;
int month;
int year;
};
typedef struct date date;
struct Product {
char* maSanPham;
char* tenSanPham;
int soLuong;
char* donVi;
struct date ngayNhap;
bool tinhTrang;
};
typedef struct Product Product; // So we don't have to use "struct Product" everywhere.
struct date convertStringToDate(char str[]){
char* token = strtok(str,"-");
struct date d;
int i = 0;
while( token != NULL ) {
if(i == 0){
d.day = atoi(token);
token = strtok(NULL, "-");
}else if(i == 1){
d.month = atoi(token);
token = strtok(NULL, "-");
}else if(i == 2){
d.year = atoi(token);
token = strtok(NULL, "-");
}else{
break;
}
i++;
}
return d;
}
bool checkBoolean(char str[]){
return (strcmp(str,"true") == 0);
}
Product convertStringToProduct(char *str) {
char* regex = "|";
char* token = strtok(str,regex);
char* maSanPham;
char* tenSanPham;
char* donVi;
int soLuong;
char* ngayNhap;
bool tinhTrang;
int i = 0;
while(true){
if(i==0){
maSanPham = token;
}else if(i == 1){
tenSanPham = token;
}else if(i == 2){
soLuong = atoi(token);
}else if(i == 3){
donVi = token;
}else if(i == 4){
ngayNhap = token;
}else if(i == 5){
tinhTrang = checkBoolean(token);
}else{
break;
}
i++;
token = strtok(NULL, "|");
}
date fngayNhap = convertStringToDate(ngayNhap);
Product pro = {maSanPham, tenSanPham, soLuong, donVi, fngayNhap.day, fngayNhap.month, fngayNhap.year, tinhTrang};
return pro;
}
void insertProduct(Product** listProductPtr, size_t *lengthPtr, Product product) {
printf("[insertProduct]]INFO: Product Name before insert: %s \n", product.tenSanPham);
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) {
printf("ERROR__________________realloc failed");
}
*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 == NULL) {
printf("ERROR__________________can not open file");
}
volatile char buff[1024];
Product product;
while (fgets(buff, sizeof(buff), fp) != NULL) {
product = convertStringToProduct(buff);
printf("[readDataFromFile]INFO: Product Name after conver: %s \n", product.tenSanPham);
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])
const char *fileName = "products.txt";
readDataFromFile(&listProduct, &length, fileName);
printf("[main] Address of listProduct variable: %p\n", (void*)&listProduct);
if (length)
printf("[main] Address of first product: %p\n", (void*)listProduct);
size_t i;
for( i=0; i<length; ++i) {
printf("%s\n", listProduct[i].tenSanPham);
}
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.