Split/Parse a String after reading a Text File? - c

I am trying to simply read in a basic text file, split each line into separate strings and rearrange/copy them onto a new text file. Is there any simple way to split and identify these strings to be added to a new file at the end of processing the lines?
My code so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *pFileCust
fPointer = fopen("Athletes.txt", "r");
char singleLine[150];
while (!feof(pFileCust)){
fscanf(singleLine, 150);
int id, name, sport;
fprintf(%d[0,6], %s[8,15], %s[16,22], id, name, sport);
}
fclose(fPointer);
return 0;
}
Example Text File to be read into the program:
88888 John Doe Tennis
99999 Jane Smith Softball
Example Output that I am trying to achieve.
Tennis 88888 John Doe
Softball 99999 Jane Smith

Each line in your file corresponds to a record. Each series of consecutive non-whitespace characters corresponds to a field in the current record. Accordingly,
/* getrecord: read next record on fp */
char *getrecord(FILE *fp)
{
assert(fp);
char *line = malloc(MAXLINE);
if (line != NULL)
if (fgets(line, MAXLINE, fp) != NULL)
return line;
return NULL;
}
/* getfield: read next field in record */
char *getfield(const char *record, int *pos)
{
assert(record && pos);
char *record;
int ret;
if ((record = malloc(MAXRECORD)) != NULL) {
ret = sscanf(record + *pos, "%s", record);
if (ret == 1)
return record;
}
return NULL;
}
While each function does not appear to do much work, separating your business logic from record/field reading has real benefits. It allows extensibility (for example you can add error handling to these routines). You can also make more sense of your code. Now you can write your main function which will use this pair of calls.

Here is a simple adaptation of your code that (a) compiles, and (b) generates the output that you desire.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *pFileCust = fopen("Athletes.txt", "r");
char first_name[100], last_name[100], sport[100];
int id;
while (fscanf(pFileCust, "%d %s %s %s", &id, first_name, last_name, sport) != EOF) {
printf("%s %d %s %s\n", sport, id, first_name, last_name);
}
fclose(pFileCust);
return 0;
}
One of the key things your app was missing was anything assigning values to your variables; your fscanf was not doing anything (if it even compiled). fscanf is not a very GOOD way to parse text, it's not very robust. But for the principle of understanding how variables are assigned, please look carefully at that, and in particular understand why the id has an ampersand in front of it. Also, make sure you understand why I used both a first name and a last name.

Related

How would I go about reading and separating this text file's information into arrays?

Suppose I have a text file such as:
Adam: Tall Handsome Kind Athlete
He enjoys playing basketball
Sabrina: Short Pretty Funny Adorable Gymnast
She loves gymnastics
Sinclair: Blonde
He is blonde
Assume the file has several more people, each with a Name and then 0 or more characteristics about them
and then a new line with a tab following a sentence underneath.
For example,
Adam: would be the name
Tall Handsome Kind Athlete would be 4 individual characteristics
He enjoys playing basketball would be the sentence.
I want to store this information in a structure like so:
typedef struct People {
char *name;
char **characteristics;
char *sentence;
} People;
typedef struct List {
People **list;
int total_ppl;
} List;
int main (void) {
List *ppl_list = malloc(sizeof(List));
ppl_list->list = malloc(sizeof(People));
int i = 0;
FILE *pf = fopen("input.txt", "r");
if (pf == NULL) {
printf("Unable to open the file");
} else {
/* I'm not sure how to go about reading the information from here. I was thinking about using
fscanf but I don't know how to separate and store the Name, each Characteristic, and
the sentence separately. I know I will need to realloc ppl_list as more people are read from the
file. If I should change my structs to organize it better, please let me know.
*/
}
}
This answer is maybe not complete but it will help you, at least, with the processing of the lines in the text file.
Assuming a file.txt as the input file, and with the following format
Adam: Tall Handsome Kind Athlete
He enjoys playing basketball
Sabrina: Short Pretty Funny Adorable Gymnast
She loves gymnastics
Sinclair: Blonde
He is blonde
We can process this file as follows
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
/*process_info_line: process the line with the name and attributes*/
int process_info_line(char *line)
{
char *next = NULL;
char *part = strtok_r(line, ":", &next);
if (part)
printf("NAME: %s\n", part);
else
return 0;
while (part != NULL) {
part = strtok_r(NULL, " ", &next);
if (part)
printf("ATTRIBUTE: %s\n", part);
}
return 0;
}
/*process_sentence: process the line with the sentence*/
char *process_sentence(char *line)
{
line = line + 4;
return line;
}
/*is_sentence: checks if the line is a sentence, given your definition
* with a tab(or 4 spaces) at the begining*/
int is_sentence(char *line)
{
if (strlen(line) == 0)
return 0;
char *ptr = line;
int space_count = 0;
while (ptr != NULL) {
if (strncasecmp(ptr, " ", 1) != 0) {
break;
}
space_count++;
ptr++;
}
if (space_count == 4)
return 1;
return 0;
}
/*scan_file: read each of the lines of the file and use
* the previous functions to process it.*/
int scan_file(char *filename)
{
char *line_buf = NULL;
size_t line_buf_size = 0;
ssize_t line_size;
int line_count = 0;
FILE *fp = fopen(filename, "r");
if (!fp) {
fprintf(stderr, "Error opening file '%s'\n", filename);
return 1;
}
/*Get the first line of the file*/
line_size = getline(&line_buf, &line_buf_size, fp);
while (line_size >= 0)
{
line_count++;
line_buf[line_size-1] = '\0'; /*removing '\n' */
if (is_sentence(line_buf)) {
printf("SENTENCE: %s\n", process_sentence(line_buf));
} else {
process_info_line(line_buf);
}
line_size = getline(&line_buf, &line_buf_size,fp);
}
// don't forget to free the line_buf used by getline
free(line_buf);
line_buf = NULL;
fclose(fp);
return 0;
}
int main(void)
{
scan_file("file.txt");
return 0;
}
This will generate the following output
NAME: Adam
ATTRIBUTE: Tall
ATTRIBUTE: Handsome
ATTRIBUTE: Kind
ATTRIBUTE: Athlete
SENTENCE: He enjoys playing basketball
NAME: Sabrina
ATTRIBUTE: Short
ATTRIBUTE: Pretty
ATTRIBUTE: Funny
ATTRIBUTE: Adorable
ATTRIBUTE: Gymnast
SENTENCE: She loves gymnastics
NAME: Sinclair
ATTRIBUTE: Blonde
SENTENCE: He is blonde
There is a function called strtok(): https://www.tutorialspoint.com/c_standard_library/c_function_strtok.htm
Though I've never used it, the one time I had to do this I implemented a function that would separate a string into an array of pointers to pointers of chars and dynamically allocated memory for the whole block, it would look for commas and generate a new string each time it found one, my code wouldn't work in your case because it was written to specifically ignore withe spaces, though if you're not ignoring them but using them as delimitators the code gets a lot simpler.
Edit: as for getting the info out of the file I would create a buffer of an absurd size like say 32768 Bytes and use fgets(buffer, 32768, pf), though you may wanna add a check to see if even 32K chars weren't enough for the read and to deal with that, though I imagine it wouldn't be necessary.
Also this were the prototypes of the functions i implemented once, to give you a better idea of what you'd have to code:
char **separete_string (char *string, char delim);
void free_string_list (char **list);

Reading a file .txt in C with blank spaces

I trying to open a simple txt file in C, like the image bellow.
list example
The input text :
Name Sex Age Dad Mom
Gabriel M 58 George Claire
Louise F 44
Pablo M 19 David Maria
My doubt is, how can i make to identify the blank spaces in the list and jump correctly to another lines.
Here is my code:
#include <stdio.h>
int main() {
FILE *cfPtr;
if ((cfPtr = fopen("clients.txt", "r")) == NULL) {
puts("The file can't be open");
} else {
char name[20];
char sex[4];
int age;
char dad[20];
char mom[20];
char line[300];
printf("%-10s%-10s%-10s%-10s%-10s\n","Name","Sex","Age","Dad","Mom");
fgets(line,300,cfPtr);
fscanf(cfPtr,"%10s%10s%d%12s%12s",name,sex,&age,dad,mom);
while (!feof(cfPtr)) {
printf("%-10s%-10s%d%12s%12s\n",name,sex,age,dad,mom);
fscanf(cfPtr,"%19s%3s%d%12s%12s",name,sex,&age,dad,mom);
}
fclose(cfPtr);
}
return 0;
}
It works fine if I fill in all the spaces...
printf("%-10s%-10s%d%12s%12s\n",name,sex,age,dad,mom);
fscanf(cfPtr,"%19s%3s%d%12s%12s",name,sex,&age,dad,mom);
Change the order to read first, print later.
Ideally the data in your file should be separated by comma, tab, or some other character. If data is in fixed columns, then read everything as text (including integers) then convert the integer to text later.
Also check the return value for fscanf, if the result is not 5 then some fields were missing.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
FILE *cfPtr = fopen("clients.txt", "r");
if(cfPtr == NULL)
{
puts("The file can't be open");
return 0;
}
char name[11], sex[11], dad[11], mom[11], line[300];
int age;
fgets(line, sizeof(line), cfPtr); //skip the first line
while(fgets(line, sizeof(line), cfPtr))
{
if(5 == sscanf(line, "%10s%10s%10d%10s%10s", name, sex, &age, dad, mom))
printf("%s, %s, %d, %s, %s\n", name, sex, age, dad, mom);
}
fclose(cfPtr);
return 0;
}
Edit, changed sscan format to read integer directly, changed buffer allocation to 11 which is all that's needed.

Read lines from FILE

I would like to know what is the best way to read a lines from files, given I have
a file, that I'm promised that it would be as followed:
type
string table
color
string brown
height
int 120
cost
double 129.90
each time, one word then I would have 2 words.
I know that fscanf returns the value of the numbers of var it scans, and that's
why I have problem here, because one time the line has 1 argument and the next line it would have 2.
always the first line is only a char*, not longer then 10, and then the next is has 3 options..
if it is written an int then the number followed would be an int, as well as if it a double or a string.
thank you.
From the structure of file i think it can be grouped into a struct. And fscanf can be used like:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 100
typedef struct Node {
char name[SIZE];
char type[SIZE], value[SIZE];
} Node;
int main() {
FILE *pFile = fopen("sample-test.txt", "r");
if(pFile == NULL) {
fprintf(stderr, "Error in reading file\n");
return EXIT_FAILURE;
}
Node nodes[SIZE];
int nRet, nIndex = 0;
// Just to make sure it reads 3 tokens each time
while((nRet = fscanf(pFile, "%s%s%s", nodes[nIndex].name,
nodes[nIndex].type, nodes[nIndex].value) == 3))
nIndex++;
for(int i = 0; i < nIndex; i++)
printf("%s %s %s\n", nodes[i].name, nodes[i].type, nodes[i].value);
return EXIT_SUCCESS;
}
After reading the file, you can check in your structure array to find your desired int, double depending upon the value of name using sscanf as pointed by Some Programmer Dude.

Reading data from a text file in C?

So I'm pretty new at reading data from a text file in C. I'm used to getting input using scanf or hard coding.
I am trying to learn how to not only read data from a text file but manipulate that data. For example, say a text file called bst.txt had the following information used to perform operations on a binary search tree:
insert 10
insert 13
insert 5
insert 7
insert 20
delete 5
delete 10
....
With that example, I would have the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *fptr;
char *charptr;
char temp[50];
fptr = fopen("bst.txt", "r");
while(fgets(temp, 50, fptr) != NULL)
{
charptr = strtok(temp, " ");
while(charptr != NULL)
{
charptr = strtok(NULL, " ");
}
}
return 0;
}
I know that within the first while loop strtok() splits each line in the text file and within the second while loop strtok() splits off when the program recognizes a space, which in this case would separate the operations from the integers.
So my main question is, after, for example, the word "insert" is separated from the integer "10", how do I get the program to continue like this:
if(_____ == "insert")
{
//read integer from input file and call insert function, i.e. insert(10);
}
I need to fill in the blank.
Any help would be greatly appreciated!
If I were doing what you're doing, I would be doing it that way :)
I see a lot of people getting upvoted (not here, I mean on SO generally) for recommending that people use functions like scanf() and strtok() despite the fact that these functions are uniformly considered evil, not just because they're not thread-safe, but because they modify their arguments in ways that are hard to predict, and are a giant pain in the ass to debug.
If you're malloc()ing an input buffer for reading from a file, always make it at least 4kB — that's the smallest page the kernel can give you anyway, so unless you're doing a bazillion stupid little 100-byte malloc()s, you might as well — and don't be afraid to allocate 10x or 100x that if that makes life easy.
So, for these kinds of problems where you're dealing with little text files of input data, here's what you do:
malloc() yourself a fine big buffer that's big enough to slurp in the whole file with buckets and buckets of headroom
open the file, slurp the whole damn thing in with read(), and close it
record how many bytes you read in n_chars (or whatever)
do one pass through the buffer and 1) replace all the newlines with NULs and 2) record the start of each line (occurs after a newline!) into successive positions in a lines array (e.g. char **lines; lines=malloc(n_chars*sizeof(char *)): there can't be more lines than bytes!)
(optional) as you go, advance your start-of-line pointers to skip leading whitespace
(optional) as you go, overwrite trailing whitespace with NULs
keep a count of the lines as you go and save it in n_lines
remember to free() that buffer when you're done with it
Now, what do you have? You have an array of strings that are the lines of your file (optionally with each line stripped of leading and trailing whitespace) and you can do what the hell you like with it.
So what do you do?
Go through the array of lines one-by-one, like this:
for(i=0; i<n_lines; i++) {
if( '\0'==*lines[i] || '#' == *lines[i] )
continue;
// More code
}
Already you have ignored empty lines and lines that start with a "#". Your config file now has comments!
long n;
int len;
for(i=0; i<n_lines; i++) {
if( '\0'==*lines[i] || '#' == *lines[i] )
continue;
// More code
len = strlen("insert");
if( 0== strncmp(lines[i], "insert", len) ) {
n = strtol(lines[i]+len+1, &endp, 10);
// error checking
tree_insert( (int)n );
continue;
}
len = strlen("delete");
if( 0== strncmp(lines[i], "delete", len) ) {
n = strtol(lines[i]+len+1, &endp, 10);
// error checking
tree_delete( (int)n );
}
}
Now, you can probably see 10 ways of making this code better. Me too. How about a struct that contains a keywords and a function pointer to the appropriate tree function?
Other ideas? Knock yourself out!
you can call as follows.For example i have put printf but you can replace your insert/delete function instead that.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *fptr;
char *charptr;
char temp[50];
fptr = fopen("bst.txt", "r");
while(fgets(temp, 50, fptr) != NULL)
{
charptr = strtok(temp, " ");
if(strcmp(charptr,"insert")==0)
{
charptr = strtok(NULL, " ");
printf("insert num %d\n",atoi(charptr));
}
else if(strcmp(charptr,"delete")==0)
{
charptr = strtok(NULL, " ");
printf("delete num %d\n",atoi(charptr));
}
}
return 0;
}
I think the best way to read formatted strings in file is using fscanf, the following example shows how to parse the file. You could store the charptr and value for further operations:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *fptr;
char charptr[50];
int value;
fptr = fopen("bst.txt", "r");
while (fscanf(fptr, "%s%d", charptr, &value) > 0)
{
printf("%s: %d\n", charptr, value);
}
return 0;
}
try this code
int main(){
FILE *fp;
char character[50];
int value;
fptr = fopen("input.txt", "r");
while (fscanf(fp, "%s%d", character, &value) > 0)
{
if(strcmp(character,"insert")==0){
insert(value);//call you function which you want value is 10 or change according to file
}
}
return 0;
}

Using "fscanf" in C How can Split two strings?

I want to a linked list in C using file operations. I want to get a line and split it and storage in structers. But I cant split two strings.
My File like this:
1#Emre#Dogan2#John#Smith3#Ashley#Thomasetc...
I want to read one line from file using fscanf.
fscanf(file,"%d#%s#%s",&number,name,surmane);
But the result is
Number : 1Name : Emre#Dogan
How can get rid of that # element in the name and split it to name and surname;
#include <stdio.h>
#include <string.h>
int main(void) {
FILE *fptr;
fptr = fopen("Input.txt", "r");
int number;
char *name;
char *surname;
char line_data[1024];
fgets(line_data, 1024, fptr);
number = atoi(strtok(line_data, "#"));
name = strtok(NULL, "#");
surname = strtok(NULL, "#");
printf("%d %s %s", number, name, surname);
}
Output:
1 Emre Dogan
EDIT:
Coverted the variable "number" from string to integer.
It's better to read a full line using fgets(), then parsing that line. This is more robust, using fscanf() directly on the input stream can be confusing due to the way fscanf() skips whitespace.
So, you could do:
char line[1024];
if(fgets(line, sizeof line, file) != NULL)
{
int age;
char name[256], surname[256];
if(sscanf(line, "%d#%255[^#]#%255s", &age, name, surname) == 3)
{
printf("it seems %s %s is %d years old\n", name, surname, age);
}
}
This uses the %[] format specifier to avoid including the # separator in the parsed strings. I think this is cleaner than strtok(), which is a scary function best avoided.

Resources