Problem

12/30/2017 00:51 Aeneis Boost#1
Code:
struct Blood{
	int  ID;
   char  Nev[50];
   char  Vercsoport[50];
   char  Email[100];
   int   Verszam;
   char  Datum[50];
};
int main (int argc, char *argv[] )
{
FILE *f = fopen(argv[1], "r");
struct Blood blood[50];
char ideig[500];
int i = 0;
while(fgets(ideig, 500 , f)){
	blood[i].Nev = strtok(ideig,"\t");
	blood[i].Vercsoport = strtok(NULL,"\t");
	blood[i].Email = strtok(NULL,"\t");
	blood[i].Verszam = strtok(NULL,"\t");
	blood[i].Datum = strtok(NULL,"\t");
	i ++;
}
fclose(f);
trying to read a file with main arguments and putting it into an array but it doesnt work.
is there an easier way to do this and does someone know what might be the problem? (Sorry if it seems really dumb i dont quite get this strtok yet)
Is there a way to do this without using string.h?
Thanks in advance
12/30/2017 05:40 Underfisk#2
Gotta recommend you to try to use json or csv lib, will be easier to store objects values than pure text.
There are couple json and csv libs for c++, pick one and use it so you'll figure out better and find that it's easier to use it.
12/30/2017 06:31 algernong#3
Hi,

since the primary goal of your application is to get familiar with C and its standard library, I'd refrain from using 3rd-party libraries to get the job done.

I can't test it right now, but one error is your usage of strtok.

You create an array with 50 characters "ideig" on the stack, i.e. "ideig" is always one and the same memory location. When you call fgets, it reads data from the file and places it at &ideig. So if you call fgets a second time, the data that was read previously is overwritten (since the new data is also stored at address &ideig). Thus, you must make sure that you don't need old data anymore before you overwrite it.

That's where your code fails; lets take a look at how strtok works.
Lets say we have
Code:
char t[80] = "A short sentence."
I.e. somewhere in memory, we have
Code:
|A| |s|h|o|r|t| |s|e|n|t|e|n|c|e|.|\0|...
and the first "A" is at address &t, the following white space at address &t+1 and so on.

Now, you call
Code:
char *ptr = strtok(t, " ");
ptr points to the first "A", i.e. the start of the token, but strtok also modifies the contents of "t": it replaces the first white space with a "\0", i.e. the contents of "t" after this call is:
Code:
|A|\0|s|h|o|r|t| |s|e|n|t|e|n|c|e|.|\0|...
ptr == t
Next, call
Code:
ptr = strtok(NULL, " ");
After this call, we get
Code:
|A|\0|s|h|o|r|t|\0|s|e|n|t|e|n|c|e|.|\0|...
ptr == t + 2
I.e. strtok replaces the second white space with "\0" (the end of the second token) and returns the address to the start of the second token, i.e. t + 2 (we skip the first two characters, i.e. "A" and "\0", since that's the first token).
If we call strtok again, we have
Code:
|A|\0|s|h|o|r|t|\0|s|e|n|t|e|n|c|e|.|\0|...
ptr == t + 8
The important observation is that ptr is always a pointer somewhere to the contents of "t". Thus, if you call fgets again, ptr is no longer valid, since we replaced the data that is points to with something else (the next line in the file).

To fix this, you must copy the text, i.e. use
Code:
while(fgets(ideig, 500 , f)){
        strcpy(blood[i].Nev, strtok(ideig,"\t"));
	strcpy(blood[i].Vercsoport, strtok(NULL,"\t"));
	[...]
	i ++;
}
(strcpy is also declared in string.h)

Also, you can't assign a char pointer to an integer (or at least it doesn't do that you're expecting in your code). Use
Code:
blood[i].Verszam = atoi(strtok(NULL, "\t"));
"atoi" turns a string that is a number into that number, i.e. atoi("123") == 123

Sorry if most of my post is too obvious
12/30/2017 19:38 MartinaLaMartona#4
Code:
while(fscanf(ideig, "%s %s %s %d %s\n", blood[i].Nev, blood[i].Vercsoport, blood[i].Email, &blood[i].Verszam, blood[i].Datum) == 5)
{
	i++;
}
fclose(f);
If your file is formatted, read objects on file through this way, it's easier!
12/31/2017 15:27 Aeneis Boost#5
Thank you @[Only registered and activated users can see links. Click Here To Register...] your code seems to work perfectly
and thanks @[Only registered and activated users can see links. Click Here To Register...] for the explanation!

Code:
int getdate(char *date){
	
	char storage[100];
	long final;
	int i;
	
for (i = 0; date[i] != 0; i++) {
	char c = date[i];
	if(c != '.'){
	strcat(storage,c);
	}
	}
	final = atoi(storage);
	return final;
}
trying to make something that converts this : 1992.12.12.
to this : 19921212
i might be an idiot but i dont know what the problem is
01/01/2018 14:15 maxi39#6
Code:
#include <stdio.h>

long long longPow(int a,int b){
long long result = 1;
for(int i = 1; i <= b;i++)
    result *= a;
return result;
}

long long CtoI(char* date){
long long result = 0;
int p = 7;
for(int i = 0; i < 10;i++) //assuming the date has always 10chars
if(date[i] != '.'){
   result += (long long) (((int)date[i] - 48) * longPow(10,p));
   p--;
}
return result;
}

int main(){
  char* test = "1999.02.06";
printf("%llu",CtoI(test));
return 0;
}
01/01/2018 14:26 Aeneis Boost#7
um yea thanks this works however its a bit complicated for me... care to explain?
01/01/2018 19:32 algernong#8
Quote:
i might be an idiot but i dont know what the problem is
First:

The first parameter of strcat() must be a null-terminated string. Since you declare storage on the stack without initialization, it contains random data, i.e. it's not a null terminated string. To fix this, explicitly set the first entry of storage to '0', i.e.
Code:
char storage[200];
storage[0] = 0; // storage is a null terminated string of length 0
or simply
Code:
char storage[200] = {0}; // this actually sets all entries to 0, not just the first one

Secondly:

When I compile your code with GCC, I get the following warning:
Quote:
test.c:12:17: warning: passing argument 2 of ‘strcat’ makes pointer from integer without a cast [-Wint-conversion]
strcat(storage,c);
Indeed, the signature of strcat is as follows:
Code:
char * strcat ( char * destination, const char * source );
So the second parameter must be a pointer to char (= C string). But you pass a char as second parameter.
Compilation doesn't fail because the character gets implicitly casted to an address, i.e. if your char is '0' == 48, 48 is interpreted as an address. But that's probably not what you want; thus, you should get a warning.

If you want to fix your own code, I see two options:

Replace
Code:
strcat(storage,c);
with
Code:
char tmp[] = {c, 0}; strcat(storage, tmp);
I.e. create a temporary string that only has one character, namely c (and null termination!), then pass that string as second parameter.
Note that
Code:
strcat(storage, &c);
wouldn't work because then there's no null termination (the code would compile without warnings though).

Or don't use strcat():
Code:
	int j = 0;
	for (i = 0; date[i] != 0; i++) {
		char c = date[i];
		if(c != '.'){
			storage[j] = c;
			++j;
		}
	}
	storage[j] = 0; // don't forget 0-termination!
maxi39's code is more complicated because it doesn't use atoi(). But this can be done more efficiently, you don't need the longPow() function:
Code:
int getdate(const char *date){	
	int number = 0;
	while (*date) { // aborts if *date == 0
		if (isdigit(*date)) { // skip anything that is not a digit
			number *= 10; // move previous digits to the left
			number += *date - '0'; // add new digit
		}
		++date;
	}
	return number;
}
The idea of the code is as follows: Let's say you want to turn the string "123" into an int; consider the string digit by digit, from left to right.
The first digit is 1, number = 1
Since there are more digits, move "1" to the left by multiplying number with 10: 10 * number = 10
Now add the next digit, 2: number = 10 + 2 = 12
Again, since there are more digits, move the previous digits one to the left: 10 * number = 120
And add the next digit: number = 120 + 3 = 123
Since there are no more digits in this example, return number

In general, if you have an integer A and want to append a digit D to the right, use A' = 10 * A + D.
01/01/2018 21:39 Aeneis Boost#9
yeaaa i was really overcomplicating the whole thing

Code:
	int j = 0;
	for (i = 0; date[i] != 0; i++) {
		char c = date[i];
		if(c != '.'){
			storage[j] = c;
			++j;
		}
	}
	storage[j] = 0; // don't forget 0-termination!
this is perfectly fine for me