I have an document with some telephone number and andresses.
I now try to copy the numbers in one part of a struct and the adress into another.
At the moment I was just able to get the data of the document but I can't put it in my struct please help me
C Code
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
struct telefon{
char nummer[16];
char adresse[128];
};
typedef struct telefon TELEFON;
void main()
{
TELEFON tel;
char buffer[256];
FILE *fp;
int i = 0;
int countSemi = 0;
fp = fopen("Telefondatei.txt", "r");
if(fp == NULL)
{
printf("Datei konnte nicht geoeffnet werden.\n");
}
else{
while(fgets(buffer,1000,fp) != 0){
//printf("%s\n",buffer);
while(buffer != 0){
i++;
if(buffer[i] == ';'){
countSemi++;
}
while(countSemi <= 7){
strcpy(tel.adresse,buffer);
printf("%s\n %d \n",tel.adresse,countSemi);
}
}
}
}
}
Example for the data in my .txt document
"Firma";"";"Auto GmbH";"gasse 3";"5000";"Mon";"";"0456";"45652"
"Firma";"";"ADAC";"";"50000";"Mon";"";"2156";"545218"
You will need to use strtok additionally. See this example. However, please note this example assumes the data is written in fixed format (and it will not work if data comes in other format - you might want to modify this for your needs, this is just illustration):
Assumed data format for each line:
Address;telephoneNumber;
#include <string.h>
..
char * value;
while(fgets(buffer,256,fp) != 0)
{
value = strtok(buffer, ";"); // get address
strcpy(tel.adresse, value);
value = strtok(NULL, ";"); // get number
strcpy(tel.nummer, value);
}
Also this:
while(buffer != 0)
in your code doesn't make sense. Hardly buffer will be 0. It is array and value of buffer will always be memory address where that array starts. You can't assign to buffer.
Here is another post about using strtok.
To get your data use : fscanf(fp, "%s %s %s %d", str1, str2, str3, &number);
or you can use getc to get one character but u need to test the EOF
Related
While I am aware there are libraries for config file parsing I have tried to write my own implementation. The problem is that I can find the config option but comparing the string before the delimeter failes when I try to compare it with the thing I am searching for. I need to comare it with the thing I am searching for becasue my program allows things like Test2 and Test3 because it cannot check if there are characters before or after the word Test. The compare allways failes and I cannot figure out why.
Here is my code:
Main.c
#include <stdio.h>
#include <stdlib.h>
void Parser(char *CONFIG_FILE, int *P_VALUE, char *STRING_TO_LOOK_FOR);
int main(){
int VALUE;
Parser("config.txt", &VALUE, "Test");
printf("%d \n", VALUE);
}
Parser.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void Parser(char *CONFIG_FILE, int *P_VALUE, char *STRING_TO_LOOK_FOR){
FILE *FP=fopen(CONFIG_FILE,"a+");
char TMP[256]={0x0};
int i = 1;
while(FP!=NULL && fgets(TMP, sizeof(TMP), FP)!=NULL){ //Loop through every line
i=i+1; //Increment the line number
if (strstr(TMP, STRING_TO_LOOK_FOR)){ //Is the term im looking for in this line
char *NAME_OF_CONFIG_STR = strtok(TMP, "= "); //look for delimiter
char *STRVALUE = strtok(NULL, "= "); //Get everything past the delimiter
char *P_PTR;
char *pos;
if ((pos=strchr(NAME_OF_CONFIG_STR, '\n')) != NULL){ //attempt remove \n doesn't work
*pos = '\0';
}
if(strcmp(STRING_TO_LOOK_FOR, NAME_OF_CONFIG_STR) == 0){ //try to check the two are the same
*P_VALUE = strtol(STRVALUE, &P_PTR, 10); //Returns an integer to main of the value
}
}
}
if(FP != NULL){
fclose(FP);
}
}
config.txt:
Test= 1234
Test2= 5678
Test3= 9012
Thanks to BLUEPIXY and the demo they created this problem has been solved. The issue was in the gcc comiler options I had forgotten -std=99 somehow this caused the program to behave correctly.
I'm a student, I am wondering...
How can I make a program that can Get some data from my text file to a variable on my program and print them
Example:
My Text File
I,Ate,Cookies
She,Drink,Coffee
Tom,Wears,Pyjamas
My code
main()
{
FILE *fp=fileopen("c:\\textfile.txt","r");
char name[20],action[20],item[20];
prinf("Enter name: \n");
scanf("%s",&name);
/* I dont Know what to do next */
}
I though about some checking code:
if (name==nametxt) /*nametxt is the first line on the text file */
{
printf("%s\n %s\n %s\n",name,action,item);
}
If the name is "I",the output would look like this :
Enter name:
I
I
Eat
Cookies
A help will satisfy my curiosity thanks in advance
You are reading characters from file until you receive new line character (\n) or fill an array, then you return characters stored in an array passed by caller.
From this returned array you may get separated values with strtok.
Repeat until you receive 0 from getline (Getline received EOF from file.)
Here is simple example with your own getline function which you may modify.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int getline(char s[],int lim, FILE * fp)
{
int c, i;
for (i=0; i < lim-1 && (c=fgetc(fp))!=EOF && c!='\n'; ++i)
{
s[i] = c;
}
if (c == '\n')
{
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
int main()
{
FILE * fp = fopen("c:\\textfile.txt", "r");
char line[100];
char * ptr;
while (getline(line, 100, fp))
{
ptr = strtok(line, ",");
while( ptr != NULL )
{
printf(" %s\n", ptr);
ptr = strtok(NULL, ",");
}
}
return 0;
}
Output
I
Ate
Cookies
She
Drink
Coffee
Tom
Wears
Pyjamas
Storing strings into variable isnt tough, here is an example
strcpy(name, ptr);
But be careful, writing outside of bounds have undefined behavior.
strncpy(name, ptr, 100); You can limit number of copied characters with strncpy, but be careful, this function is error-prone.
You can do like this,
Go on reading characters from a file, after every character is read compare with ',' character.
If the character read is ',' then you have finished reading the name, otherwise store it in a character array and continue reading the file.
Once you hit ',' character, terminate the character array with null character(Now you have a complete name with you).
Compare this character array with a string you receive as input using a strcmp(String compare function). If its it matches decide what you wanna do?
I hope i am clear.
There is different ways to read data from a FILE * in C :
You read only one character : int fgetc(FILE *fp);.
You read a whole line : char *fgets(char *buf, int n, FILE *fp); (take care to buf, it must point to allocate memory).
You read a formatted string, which is your case here : int fscanf(FILE *stream, const char *format, ...), it works like printf() :
This way :
char name[20], action[20], item[20];
FILE *f = fopen("myfile.txt", "r");
if (! f)
return;
if (3 == fscanf(f, "%19[^,\n],%19[^,\n],%19[^,\n]\n", name, action, item))
printf("%s %s %s\n", name, action, item)
%30[^,\n], here is used to read of whole object of your line, except , or \n, which will read item by item the content of your string.
start with like this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DATA_FILE "data.txt"
#define LEN 19
#define SIZE (LEN+1)
//Stringification
#define S_(n) #n
#define S(n) S_(n)
enum { NOT_FOUND, FIND };
int pull_data(const char name[SIZE], char action[SIZE], char item[SIZE]){
int ret = NOT_FOUND;
FILE *fp = fopen(DATA_FILE, "r");//fileopen --> fopen
if(fp == NULL){
perror("fopen:");
exit(EXIT_FAILURE);
} else {
char nametxt[SIZE];
*action = *item = 0;
while(fscanf(fp, "%" S(LEN) "[^,],%" S(LEN) "[^,],%" S(LEN) "[^\n]%*c", //"%19[^,],%19[^,],%19[^\n]%*c"
nametxt, action, item) == 3){
if(strcmp(name, nametxt) == 0){//Use strcmp for comparison of strings
ret = FIND;
break;
}
}
}
fclose(fp);
return ret;
}
int main(void){
char name[SIZE], action[SIZE], item[SIZE];
printf("Enter name: \n");//prinf --> printf
if(scanf("%" S(LEN) "s", name) == 1){
if(pull_data(name, action, item) == FIND){
printf("%s\n%s\n%s\n", name, action, item);
} else {
printf("%s not found.\n", name);
}
}
}
The input text file has some numbers per line, numbers are split by space. The first two lines only got one number, and the following lines got three. What I want to do is read each line of the input and store these numbers.
This is what I've got so far:
int
main(int argc, char *argv[]) {
int n = 0;
char buff[MAX_STRING_LEN]; //MAX_STRING_LEN is defined as 64
while (fgets(buff,MAX_STRING_LEN, stdin) != NULL) {
char temp;
if (n == 0) {
sscanf(buff, "%s", &temp);
int h_num = (int)temp;
} else if (n == 1) {
sscanf(buff, "%s", &temp);
int s_num = (int)temp;
} else {
sscanf(buff, "%s", &temp);
char *token;
token = strtok(&temp, " ");
int i = 0;
int a,b,c;
while (token != NULL) {
if (i == 0) {
a = (int)token;
token = strtok(NULL, " ");
} else if (i == 1) {
b = (int)token;
token = strtok(NULL, " ");
} else {
c = (int)token;
token = strtok(NULL, " ");
}
i++;
}
}
n++;
}
return 0;
}
The print statement I used to test my code is like:
printf("%d\n",h_num);
printf("%d\n%d\n%d\n",a,b,c);
I created a text file like this:
23
34
4 76 91
but the output is not what I expected, it's the address of the pointer I think. (I'm stuck with pointer again =( )
Could someone help me to point out what the problem is? Appreciate it.
In your code, I can see,
int h_num = (int)temp;
and
int s_num = (int)temp;
No, that is not how you convert an aphanumeric string to int.
You need to use strtol() for this purpose.
Then,
sscanf(buff, "%s", &temp);
is wrong. temp is a char, you got to use %c for that.
My suggestion for a better approach:
Read a complete line from file using fgets()
tokenize the input using strtok(), using space () as delimiter, then convert the token (if not NULL) to int using strtol()
continue untill the returned token is NULL
In this case, your code will be much more generic, as don't need to bother seperately about the number of ints present in each line.
So, my goal is to create a linear search, but i have got that down pat, I am having one problem with accessing strings from the struct, that i have stored using a txt file, so in linearSearch() I tried doing this:
printf("Name: %s \n", q.name[i]);
printf("Data: %d \n", q.data[i]);
The data would be perfect but name would just print out the same name for every array which would be the last item that I put into the array.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char* name[10];
int data[10];
}Word;
//int bubblesort (Word word);
void linearSearch(char* name, Word q);
int main (int argc, const char *argv[]){
Word q;
char username[9]; /* One extra for nul char. */
int score;
int i = 0;
FILE *ifp, *ofp;
ifp = fopen("Data.txt", "r");
while (fscanf(ifp, "%s %d", &username, &score) == 2) {
q.name[i] = username;
printf ("Name: %s, I = %d \n", q.name[i], i);
q.data[i] = score;
printf ("Data: %d, I = %d \n", q.data[i], i);
i++;
}
linearSearch("Matt", q);
return EXIT_SUCCESS;
}
void linearSearch(char* name, Word q){
int i = 0;
int foundIt = 0;
int numNames = sizeof(&q.name);
while ((foundIt == 0) && (i <= numNames)){
printf("Name: %s \n", q.name[i]);
printf("Data: %d \n", q.data[i]);
if ((strcmp(name, q.name[i]) != 0)){
i = i + 1;
} else {
foundIt = 1;
}
}
if (foundIt == 1){
printf("Name found at position %d", i);
} else {
printf("Required person not found");
}
}
This happens because of the code
q.name[i] = username;
You cannot assign the value of an array using = operator. Here, you're assigning the address of username to every q.name[i]. So, the last value of username is reflected throughout the array.
What you actually need is to use malloc() to allocate memory and then strcpy() to copy the string contents.
Otherwise, you can also make use of strdup().
Either way, don't forget to free() the allocated ememory once you're done using them.
I can see that you declared char username[9], so I assume your names should be at most 8 characters long. You should :
read with : fscanf(ifp, "%8s %d",&username, &score) == 2 : the & is useless in front of an array (it decays nicely to a pointer), but you should limit size of input - ok , your problem does not come from there
use a 2D char array for Word.name instead of an array of pointers. That way your memory is already allocated and you can safely strcpy to it :
typedef struct {
char name[10][9];
int data[10];
}Word;
then :
strcpy(q.name[i], username); /* safe because qname[i] and username are both [9] */
The rule here is always control that you do not risk a buffer overrun when writing in char arrays/
An alternative way would be to do dynamic allocation through strdup but in that case you should free it.
I am trying to read from a file into array.
My file called Players.txt contains:
Del Piero|3|Italy|Juventus|
Ronaldo|0|Portugal|Real Madrit
I used fscanf , but it is not working correctly , I am not doing right the conversion.
can anyone help me to read and store them into arrays. Like the array player name to contain { Del Piero, Ronaldo}
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <ctype.h>
#define NUM_PLAYERS 20
#define NAME_LENGTH 100
#define COUNTRY_NAME 20
int main (void)
{
FILE *Players;
char player_name [NUM_PLAYERS][NAME_LENGTH] = {0};
char country_name[NUM_PLAYERS][COUNTRY_NAME] = {0};
char team_name[NUM_PLAYERS][NAME_LENGTH] = {0};
int goals_scored[NUM_PLAYERS] = {0};
int i;
Players = fopen("G:\\COP2220\\Project 5\\Players.txt", "r");
if (Players == NULL)
{
printf("File not found.\n");
}
else
{
while (fscanf(Players, " %[^|]s %[^|]d %[^|]s %[^|]s",player_name[i],&goals_scored[i],country_name[i],team_name[i]))
{
printf("The player %s, scored %d from %s plays in %s\n", player_name, goals_scored,country_name, team_name );
}
}
fclose(Players);
return 0;
}
[] is a type all in itself, you shouldn't append s or d at the its end. All you really have to do is change the format to this:
"%[^|] | %d | %[^|] | %[^|]|\n"
And consider changing your while loop to break when fscanf doesn't return 4.
Here's some working code:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <ctype.h>
#define NUM_PLAYERS 20
#define NAME_LENGTH 100
#define COUNTRY_NAME 20
int
main (void)
{
FILE * Players;
char player_name [NUM_PLAYERS][NAME_LENGTH] = {0};
char country_name[NUM_PLAYERS][COUNTRY_NAME] = {0};
char team_name[NUM_PLAYERS][NAME_LENGTH] = {0};
int goals_scored[NUM_PLAYERS] = {0};
int i = 0, ret = 0;
Players = fopen("testfile", "r");
if (Players == NULL)
{
printf("File not found.\n");
}
else
{
for (;;)
{
ret = fscanf(Players, "%[^|] | %d | %[^|] | %[^|]|\n",
player_name[i],
&goals_scored[i],
country_name[i],
team_name[i]);
if (ret != 4)
{
printf ("only %d arguments were matched\n", ret);
break;
}
printf("The player %s, scored %d from %s plays in %s\n",
player_name[i],
goals_scored[i],
country_name[i],
team_name[i]);
i++;
}
fclose(Players);
}
return 0;
}
The scanf format %[^|]s reads a string of non-| characters followed by an s character, which can never match (since the next character after the string, if it exists, must be a |, not an s). You probably want something more like:
while (4 == fscanf(Players, " %99[^|\n]|%d| %19[^|\n]| %99[^|\n]", player_name[i], &goals_scored[i], country_name[i], team_name[i]))
Note the additional string size limits to avoid overflowing arrays, and the newlines in the patterns, so that they can't be included in any of the strings (but can appear between strings).
Note also that this will match your second line, but will leave |Madrit to be read by the next call to fscanf, so you might want to put
fscanf(Players, "%*[\n]%*c");
in the loop to read the rest of the line up to the newline and throw it away.
You never actually consume the "|" characters in between your fields. Instead you're only reading up until the "|" character. Try adjusting your format string to something like:
"%[^|]|%[^|]d|%[^|]|%[^|]"
Your format scan string is incorrect. The %[..] is itself the format specifier, adding the s or d after it is just taken to be a literal s or d in the scan string, and not a %s or %d like you are expecting.
Also, your printf() prints out the goals_scored address rather than the stored value for the player. You forgot to index the array.
It is possible to get your format scan string to work, but since the last field appears optional, you have some complexity to deal with that case. In the code below, we deal with this by explicitly calling out that the newline should not be part of the last field. Then the %*c will discard either the | or the \n at the end. The space at the end of the scan string allows fscanf() to move to the next line in the case that the | was discarded.
while (fscanf(Players, " %[^|]|%d|%[^|]|%[^|\n]%*c ",
player_name[i], &goals_scored[i], country_name[i], team_name[i]) == 4)
{
printf("The player %s, scored %d from %s plays in %s\n",
player_name, goals_scored[i], country_name, team_name);
}
However, this problem seems ideal for strtok(). The advantage is that you have more control over how to deal with each field, and you can get more information about where errors are occurring during a parse of the line.
int parse_line (char *buffer,
char *name, int *goals, char *country, char *team,
char **rest)
{
char *tok = strtok(buffer, "|");
int count = 0;
while (tok && count < 4) {
++count;
switch (count) {
case 1: strcpy(name, tok); break;
case 2: *goals = atoi(tok); break;
case 3: strcpy(country, tok); break;
case 4: strcpy(team, tok); break;
default: break;
}
tok = strtok(0, "|");
}
*rest = tok;
return count;
}
You would change your code to read in a line of data, and then feed that line to the parse_line() function.
char buf[MAX_LINE_LENGTH];
char *rest;
while (fgets(buf, sizeof(buf), Players) != 0) {
parse_line(buf,
player_name[i], &goals_scored[i], country_name[i], team_name[i],
&rest);
printf("The player %s, scored %d from %s plays in %s\n",
player_name, goals_scored[i], country_name, team_name);
}