C programming- array

I get this two warnings when im trying to run my program. I can´t seem to solve it. However when im removing the [100] infront of the char-types I get no error but the program shutsdown when I start it.

I need to store the data from a textfile in a struct with maximum capacity of 100 items. And then later on be able to sort, save, and add items. But i´m stuck on this part though.

here is an exemple of 1 item from the textfile:

82476,Watermelon Dorado Double India Pale Ale,31.90,355.00,Ale brittisk-amerikansk stil,Imperial/Dubbel IPA,Flaska,USA,Ballast Point Brewing,10.00

warning: passing argument 1 of 'strncpy' from incompatible pointer type [-Wincompatible-pointer-types]
strncpy(&items[i].producent, tok, strlen(tok));

and


expected 'char *' but argument is of type 'char (*)[50]'
_CRTIMP __cdecl __MINGW_NOTHROW char *strncpy (char *, const char *, size_t);


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
  {

	char *oneline, *tok;
	char envara[512];
	char delim[] = ",";
	FILE *fp;



	int i;
	struct vara
	{
		int nummer;
		char namn[100];
		float pris;
		float volym;
		char typ[100];
		char stil[100];
		char forpackning[20];
		char land[20];
		char producent[50];
		float alkoholhalt;

	} items[100];

	items[i].nummer = atoi(tok);
	items[i].pris = atof(tok);
	items[i].volym = atof(tok);
	items[i].alkoholhalt = atof(tok);
	strncpy(&items[i].namn, tok, strlen(tok));
	strncpy(&items[i].typ, tok, strlen(tok));
	strncpy(&items[i].stil, tok, strlen(tok));
	strncpy(&items[i].forpackning, tok, strlen(tok));
	strncpy(&items[i].land, tok, strlen(tok));
	strncpy(&items[i].producent, tok, strlen(tok));



	if ((fp = fopen("varor.csv", "r")) == NULL)
	{
		fprintf(stderr, "Filen varor.csv gick inte att öppna\n");
		exit(-1);
	}
	for (i = 0; i < 100 && fgets(envara, 512, fp); i++)
	{

		envara[strlen(envara) - 1] = '0';
		printf("%s\n\n", envara);
		oneline = strdup(envara);
		tok = strtok(oneline, delim);




		while (tok != NULL)
		{
			printf("%s\n", tok);
			tok = strtok(NULL, delim);

		}

	}


	free(oneline); free(tok);
	fclose(fp);


}
Last edited on
Hello emano12,

Let me say that this is a C program on a C++ forum, so do not expect much.

I would guess that if this does compile for you that you must have an old compiler. because I can not compile the program with the newer version that I have.

You are missing the header files that you used and "int main()" along with anything that is in between these parts.

In the "strncpy" fouctions the use of the "&" is not needed. This will eliminate some errors.

Line 5 is better written as char delim = ',';. This is not an array just a single character.

In lines 26 - 35 the value of "i" never changes and since "i" was not initialized to a value there is no telling what will be in this variable which will be a big problem. Even if you set "i" to zero the value of "i" never changes. Also you are trying to string copy information that does not yet exist because you are doing this before you read from the file.

Look through your logic and see if it really makes any sense in this order.

Hope that helps,

Andy
Hi and thanks. I´ve corrected the errors you mentioned and now i can compile the program but it stops working after I select this part.(I have a menu). I have the int main() part aswell just didnt copy it to the text somehow. Might these issue of crashing be caused by the "i" not being initialized? How can I fix this. im fairly new in C
Hello emano12,

Sorry that this got away from me and it took me longer to fine you reply.

You have made changes to your program, so you really need to post the new code so I can see what you have done.

It has been many years since I worked with a C program and I could use all the input I can get.

Yes an uninitialized variable only only reserves storage space for the variable. What ever is in that memory space is considered garbage information. On my computer an int variable will usually contain the number (-858993460) and if this variable is used before receiving a valid number the result is undefined. In your case "i" not having a starting value would mean that the subscript of the array will most likely be outside the boundary of the array.

What you did and what I might do are likely to be very different.

Post your new code and I will load it up and see what I can find.

Hope that helps,

Andy
https://codeshare.io/2EJZWP

here is my code for the moment, it is working just fine. But i need to sort the items in numerical(sorted by "nummer") and alphabetical(sorted by "namn" order, and I dont know how to start. Been googling around and found something named qsort but can´t work it out.
Well all of your strncpy() calls are still wrong. Why are you trying to limit the copy using an unknown strlen()? The length of the string pointed to by tok is unknown and could be much larger than the array you want to force it into.

qsort is just someone's quick sort code. Which there should be a billion versions of on google.

sorting by number is easy. if its text, you convert it to a number using atoi (ints) or atof (doubles) and use one of the common sorting algorithms for an array, which are all over the internet or if you have never done one, see if you can code it up yourself.

sorting by strings depends on what you want. I can't recall if using strcmp is sufficient for alphabetical, and you may want to up-case or lower-case the data before sorting (or at least in a temporary in the comparison) else you get AA BB CC aa bb cc instead of AA aa BB bb etc. If strcmp isnt sufficient, you will have to define your own comparison operator routine to do what you want done.

a lot more free sorting code is out there in c++, so you may need to make minor changes to it so C will take it. Should just be minor things.

Last edited on
qsort is just someone's quick sort code.

qsort() is a standard C function.



ah, I had forgotten that, sorry!

Take a look at this page...


http://anyexample.com/programming/c/qsort__sorting_array_of_strings__integers_and_structs.xml
Last edited on
Hello emano12,

I had to do some corrections to get the program to compile. There was no main function just void start(void). You really should use int main() with return 0; at the end of main.

I believe that "qsort" is a C++ function and not available to a C program.

The chances are that you will have to write your own sort functions, one for each sort, because I do not know of an existing sort function for C.

It may take me awhile, but I will see what I can come up with for a sort function.

Hope that helps,

Andy
I believe that "qsort" is a C++ function and not available to a C program.

No, qsort() is a standard C function that is available in C++.


The chances are that you will have to write your own sort functions, one for each sort, because I do not know of an existing sort function for C.

Please see the above, qsort() is the standard C sorting function.

Last edited on
Here is your program, updated to help you.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (b)>(a)?(a):(b)

// Rule of thumb: Keep structured TYPES out of functions.

typedef struct
{
	int nummer;
	char namn[100];
	float pris;
	float volym;
	char typ[100];
	char stil[100];
	char forpackning[20];
	char land[20];
	char producent[50];
	float alkoholhalt;

}
vara;

// A utility function to fix a design flaw with strncpy()
char *strncpy0(char *dest, const char *src, size_t count)
{
  dest[count-1] = '\0';
  return strncpy(dest, src, count-1);
}

// Write a function that does your decoding
// Don't forget to check for errors!
// s will be modified.
bool string_to_vara(char *s, vara* v)
{
        #define ssizeof(type, member) sizeof(((type*)0)->member)
        char *tok;
        if (!(tok = strtok(s,    ","))) return false;  v->nummer = atoi(tok);
        if (!(tok = strtok(NULL, ","))) return false;  strncpy0(v->namn, tok, ssizeof(vara,namn));
        if (!(tok = strtok(NULL, ","))) return false;  v->pris = atof(tok);
        if (!(tok = strtok(NULL, ","))) return false;  v->volym = atof(tok);
        if (!(tok = strtok(NULL, ","))) return false;  strncpy0(v->typ, tok, ssizeof(vara,typ));
        if (!(tok = strtok(NULL, ","))) return false;  strncpy0(v->stil, tok, ssizeof(vara,stil));
        if (!(tok = strtok(NULL, ","))) return false;  strncpy0(v->forpackning, tok, ssizeof(vara,forpackning));
        if (!(tok = strtok(NULL, ","))) return false;  strncpy0(v->land, tok, ssizeof(vara,land));
        if (!(tok = strtok(NULL, ","))) return false;  strncpy0(v->producent, tok, ssizeof(vara,producent));
        if (!(tok = strtok(NULL, ","))) return false;  v->alkoholhalt = atof(tok);
        return true;
        #undef ssizeof
}

// Write a function to compare two items
// Returns
//  • -1 : a < b
//  •  0 : a == b
//  •  1 : a > b
int jamfora_nummer(vara *a, vara *b)
{
  return (a->nummer < b->nummer) ? -1 : (a->nummer > b->nummer);
}

int jamfora_namn(vara *a, vara *b)
{
  return strcmp(a->namn, b->namn);
}

// Now we need functions useful with qsort()
int qsort_jamfora_nummer(const void *a, const void *b)
{
  return jamfora_nummer((vara*)a, (vara*)b);
}

int qsort_jamfora_namn(const void *a, const void *b)
{
  return jamfora_namn((vara*)a, (vara*)b);
}

// Main program should terminate with a value in 0..127.
// Zero is success. Anything else is error.
// Do not use negative numbers.

// Also, try not to exit(). 
// Structure your program so that it returns from main().

int main()
{
        // This is the array of items. It is the most important object here!
        const unsigned MAX_NITEMS = 100;  // Specify a maximum size for your array
	vara items[MAX_NITEMS];
        unsigned nitems = 0;              // Keep track of the USED part of your array

        // This is your temporary buffer and file pointer.
        // They are needed to read the file.
	char envara[512];
	FILE *fp;

	if ((fp = fopen("varor.csv", "r")) == NULL)
	{
		fprintf(stderr, "Filen varor.csv gick inte att öppna\n");
		return 1;
	}

        // Read the list of items, up to MAX_NITEMS of them.
        while (nitems < MAX_NITEMS && fgets(envara, sizeof(envara), fp))
        {
                // If the input line is too long, we cannot continue properly.
                // Handle it here.
                char* p = strchr(envara, '\n');
                if (!p)
                {
                        fprintf(stderr, "En inmatningsrad är för lång\n");
                        return 1;
                }
        	*p = '\0';
                
                // Attempt to decode the record and add it to the list of items.
                if (!string_to_vara(envara, items+nitems)) break;
                nitems += 1;
        }
        
        // We are done with the file. Close it now.
	fclose(fp);
        
        // Sort the items by number, name.
        // (Pay attention to the order in which this is done: first name, then number!)
        qsort(items, nitems, sizeof(vara), qsort_jamfora_namn);
        qsort(items, nitems, sizeof(vara), qsort_jamfora_nummer);
        
        // Print the sorted list of items.
        for (int i = 0; i < nitems; i++)
		printf("nummer: %d\n"
			"namn: %s\n"
			"pris: %f\n"
			"volym: %f\n"
			"typ: %s\n"
			"stil: %s\n"
			"forpackning: %s\n"
			"land: %s\n"
			"producent: %s\n"
			"alkoholhalt: %f\n\n",
			items[i].nummer,
			items[i].namn,
			items[i].pris,
			items[i].volym,
			items[i].typ,
			items[i].stil,
			items[i].forpackning,
			items[i].land,
			items[i].producent,
			items[i].alkoholhalt
		);
}

Make sure to break things down into smaller tasks instead of doing too many things at once. Here we: read, then sort, then print.

qsort() is an exceedingly useful function, but you must make sure to prepare the ordering functions for it properly.

Handling input errors is worth a university-level course on its own, but such courses never seem to exist. Make sure to check against input error at every opportunity, and handle it appropriately. (In this case, we simply abort.)

One thing I did not add was any kind of trim() function for the strings. If the possibility exists that your input CSV contains spaces around a field, you might want to trim. Update the string_to_vara() code so that you trim the token before copying it. For example:

strncpy0(v->namn, trim_inplace(tok," \t"), ssizeof(vara,namn));

Well, I hope this helps.
Topic archived. No new replies allowed.