i'm having a little big trouble in c. in particular im not able to save and modify a .txt file on an easy and efficient way.
the fact is: from a file.txt, i have to save all the words on a struct, and after that i will have to do some operations on this, like modify a specific word, a bubble sort, ecc ecc.
Im having problem on how to correctly save all the words in the struct, in the most generic possible way, even if a word from a line of the file is missing.
i mean:
1 line: word1 word2
2 line: word3
3 line: word4 word5
So even if a word is missing, i need to be able to save all this words, leaving something like a missing space in the struct.
the code that im posting is, at the moment, the best i can make with my hands, because i dont have any more ideas about what i should do.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define MAX (10) //<- is 10 because the max numbers of letters in any single word is less than 10
struct word{
char word1[MAX+1]; //<- here im defying a struct with 2 char. this struct will contain the words coming out from the file.
char word2[MAX+1]; //<- max+1 because i have ti give 1 space for the " " or the "/n" case.
};
struct word *file_read(FILE *fp, int *count){
int dim = 2; //<- the int dim is the dimensione
char buf[1024]; //<- a simple buffer
struct word *w;
int conv = 0; //<- another counter that i will use in sscanf
int i;
if(!(w = calloc(dim , sizeof(*w)))){
free(w);
}
while(fgets(buf, sizeof(buf),fp)!= NULL){
conv = sscanf(buf, "%s %s", w->word1, w->word2);
if(conv >= 1){ //if conv doesnt increase, just no print
printf("\n%s ", w[*count].word1);
}
if(conv == 2){ //the same operation
printf("%s", w[*count].word2);
}
i++;
if(*count>= dim){
dim *= 2;
struct word* temp = realloc(w, sizeof(*w)*dim);
if(temp != NULL){
w = temp;
} else{
free(w);
return NULL;
}
(*count)++;
}
}
return w;
}
int main(int argc, char *argv[]){ //<- the file will be passed by argv[1] argument
FILE *fp; //<- im defying the FILE type
fp= fopen(argv[1], "r"); //<- im opening the file passed from argv[1], in reading mode
if(fp == 0){ //<- if file is not loaded, the programm have to stop.
printf("FILE IS NOT LOADED");
return 1;
}
struct word *w; //<- im creating a struct pointer called w
int count= 0;
if(!(w = file_read(fp, &count))){ //<- going to do the reading subroutine
return 0;
}
//AFTER THE READING, I SHOULD BE ABLE TO SAVE ALL THE WORDS IN THE STRUCT
//AND I SHOUL BE ABLE TO DO SOME OPERATIONS, LIKE VISUALIZE IT DIFFERENT WAYS
//DO BUBBLE SORT, QSORT, MODIFY THE WORDS IN THE STRUCT, ECC...
}
so, please, how can i make it works???? thank you everybody.
i hope i've been clear :)
user3386109's suggestion of adding int conv to the word structure is good. Still there are errors:
(*count)++ is out of place, so that it's never reached. Move it to the place of the pointless i++.
In order to not store every line's words in the first structure, change all w-> to w[*count]..
Related
Im Completely new to programming but need to get a program running as part of my training. The programs ultimate goal is to read files from a database and then send them to the client who is asking for it.
Currently im just learning how to read strings from a file and write it to a different file. But my problem is that I want to print data out every time i hit a new line.
The data in the file im using is in the following format:
<DESCRIPTION>data,<DESCRIPTION>data,<DESCRIPTION>data etc.
The data is both int and chars.
Since the data is seperated with a "," i was thinking of first puting all "<DESCRIPTION>data" into substrings with the strtok function i managed to find while googling, after that i would scan only for the "DESCRIPTION" part and then put the desired data into an array that I then would print out when reaching the end of the array (end of the line) and then move on to the next line until End of file.
What functions can I use to fix this? Or how do I set up a loop that wont take forever by scanning all chars in the line everytime it wants data? If what im saying and what im doing is 2 different things I again apologize for being a total beginner at programming. I have been prgramming for a week now and this is all I could produce
#include <stdio.h>
#include <ctype.h>
void get9202() {
char
const * str;
const char s = ",";
char * token;
/*open database file*/
FILE * fp = fopen("datafile.dat", "r");
/*create array with all lines of data
I would like it to be able to handle unknown amounts of data.
current file is ~177000 lines of data.*/
int i = 0;
char line[i];
/*checking until end of file*/
while (fgets(line, sizeof(line), fp)) {
/*This part has to be included in the loop somehow but put in here
so that you might get a picture of what im trying to do.*/
while ( * str) {
if (!isspace( * str++))
i++;
else break;
/*not entirely sure how to exit this subloop
to print out the data and go to new line*/
}
/*trying to segment the string into an array of substrings
but dont know when to introduce x*/
token[x] = strtok(str, s);
while (token[x] != NULL) {
printf("%s\n,", token);
}
}
return result;
/* dont know how to return the file to main*/
flclose("datafile.dat");
}
If the data looks like this:
<SYMBOL>9202.T,<SYMSTAT>2,<MSGSTAT>0,<TIME>20:50:40.905246,<SYS_DT>2018/07/19,<SYS_TIM>20:50:40.503,<SYS_TIMU>20:50:40.503236
<SYMBOL>9202.T,<SYMSTAT>2,<MSGSTAT>0,<TIME>20:51:40.000235,<SYS_DT>2018/07/19,<SYS_TIM>20:51:39.598,<SYS_TIMU>20:51:39.598597
the expected file could look like
9202.T,2,0,20:50:40.905246
9202.T,2,0,20:51:40.000235
as the wanted pieces are being selected some will fall away.
Few problems:
Will declare zero length array.
int i=0;
char line[i];
fclose is never executed because of return also fclose needs FILE * as argument.
return result;
/* dont know how to return the file to main*/
flclose("datafile.dat");
Suggestions:
trying to segment the string into an array of substrings but dont
know when to introduce x
Use fgets with fscanf to parse your line since all the lines are identical.
dont know how to return the file to main
Define a structure with needed fields and return it to main.
Example:
typedef struct {
char symbol[50];
char symstat;
char msgstat;
char time[50];
}data;
data *get9202(int *numData) {
int memAllocated = 10;
data *mData = malloc(sizeof(*mData) * memAllocated);
FILE *fp = fopen("datafile.dat", "r");
char buf[3000];
int i = 0;
while (fgets(buf, sizeof buf, fp) != NULL) {
if (i == memAllocated) {
memAllocated *= 2;
void *temp = realloc(mData, sizeof( *mData) * memAllocated);
if (temp != NULL) mData = temp;
else break; //error
}
if (sscanf(buf, "<SYMBOL>%[^,],<SYMSTAT>%c,<MSGSTAT>%c,<TIME>%[^,]",
mData[i].symbol, &mData[i].symstat, &mData[i].msgstat, mData[i].time) == 4) {
i++;
} else {
printf("error\n"); //error
}
}
fclose(fp);
*numData = i;
return mData;
}
int main() {
int len = 0;
data *mData = get9202( &len);
int i = 0;
for (i = 0; i < len; i++)
printf("%s,%c,%c,%s\n", mData[i].symbol, mData[i].symstat, mData[i].msgstat,
mData[i].time);
if (mData) free(mData);
}
I am doing a homework assignment that requires me to create a program for making a dictionary. Most of my assignment is done, but I am stuck on the most complicated part. The part of the assignment I'm stuck on reads:
Editing a Dictionary (E)
Insert a new word (I) (15 points)
If the word is available, it should alert a message.
Otherwise, insert the new word
Delete a word (D) (15 points)
If the word is not available, it should alert a message.
Otherwise, delete the word
Editing a word (U) (10 points)
If the word is not available, it should alert a message
Currently the file I am working with looks like this:
Name of product: Dictionary
Description: Spanish to English Dictionary
Developer: Robert
Date of Creation: 12/02/2017
Number of words: 0
***************************************************************************
1. Red Rojo
2. Cat Gato
3. Apple Manzana
4. Love Amor
5. Car Carro
and I am wondering how I can read, and do the operations above. Most of the stuff on google is very complicated for my current skillset. Here is what I have so far? Can someone ELI5 the general process of what I should be doing in this case? Should I be using structs? How can I interact with the file in the way my professor wants me to? Here is my basic code I have for this section so far:
int editDictionary(char *oDict) {
char array[1000];
char temp[100];
FILE * dictPtr; // dictPtr = dictionary.dic file pointer
/* fix directory for dictionaries */
strcat(temp,"./dicts/");
strcat(temp,oDict);
strcpy(oDict,temp);
/* open dictPtr file for rw */
dictPtr = fopen (oDict,"a+");
fscanf(dictPtr,"%s",array[1]);
/* text scan values */
for(int i = 0; i <5; i ++) printf("%s", array[i]);
return 1;
}
Your task is pretty tedious and requires knowledge of some inbuilt functions in C.
Since, this is your homework assignment, providing the entire code to you would do no good in improving your current skillset. So, I will provide the code for performing the delete operation the dictionary which is the trickiest of all. Rest you have to figure out yourself. The code in delete_dict is more than enough to help you write other functions.
I've added the explanations in the code for most of the functions used but you should still look up their documentation to understand what each function does.
Code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
const char *WORD_COUNT_LABEL = "Number of words: ";
void delete_word(const char *filename, const char *word)
{
//add alerts
char read[100];
FILE *f = fopen(filename, "r");
int exists = 0; //the count of words that exist
//check if word exists
//fgets is used to read a line into the buffer/temp memory read
while (fgets(read, 100, f))
{
//strstr - finds substring
if (strstr(read, word))
{
exists++;
}
}
if (exists == 0)
{
fclose(f);
return;
}
//The main objective to read the file two times is
//because we want to edit the NUMBER_OF_WORDS in the file as well
//now we know that a word exists
//so move flie pointer to beginning
fseek(f, 0, SEEK_SET);
FILE *nf = fopen("dict_t.txt", "w");
int count;
char num[10];
char *p;
while (fgets(read, 100, f))
{
//if word count label is found update it
//return the pointer to the location of match
if (p = strstr(read, WORD_COUNT_LABEL))
{
p += strlen(WORD_COUNT_LABEL);
//incrementing the pointer to the position where number is to be updated
count = atoi(p); //converts integer from char * to int
count -= exists;
sprintf(num, "%d", count); //converts interger from int to char *
strcpy(p, num); //copy new number at that location
strcat(p, "\n");
}
else if (p = strstr(read, word))
{
//if we find the word to be deleted
//we set the first character in read as NULL
//so that nothing is written onto the new file.
read[0] = '\0';
}
//writes char * to file
fputs(read, nf);
}
//rest is self explanatory
fclose(nf);
fclose(f);
remove(filename);
rename("dict_t.txt", filename);
}
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.
I need to write a code that will print the frequency of each word from a given file. Words like "the" and "The" will count as two different words. I've written some code so far but the command prompt stops working when I try to run the program. I just need some guidance and to be pointed in the best direction for this code, or I would like to be told that this code needs to be abandoned. I'm not very good at this so any help would be very appreciated.
#include <stdio.h>
#include <string.h>
#define FILE_NAME "input.txt"
struct word {
char wordy[2000];
int frequency;
} words;
int word_freq(const char *text, struct word words[]);
int main (void)
{
char *text;
FILE *fp = fopen(FILE_NAME, "r");
fread(text, sizeof(text[0]), sizeof(text) / sizeof(text[0]), fp);
struct word words[2000];
int nword;
int i;
nword = word_freq(text, words);
puts("\nWord frequency:");
for(i = 0; i < nword; i++)
printf(" %s: %d\n", words[i].wordy, words[i].frequency);
return 0;
}
int word_freq(const char *text, struct word words[])
{
char punctuation[] =" .,;:!?'\"";
char *tempstr;
char *pword;
int nword;
int i;
nword = 0;
strcpy(tempstr, text);
while (pword != NULL) {
for(i = 0; i < nword; i++) {
if (strcmp(pword, words[i].wordy) == 0)
break;
}
if (i < nword)
words[i].frequency++;
else {
strcpy(words[nword].wordy, pword);
words[nword].frequency= 1;
nword++;
}
pword = strtok(NULL, punctuation);
}
return nword;
}
First off all:
char *text;
FILE *fp = fopen(FILE_NAME, "r");
fread(text, sizeof(text[0]), sizeof(text) / sizeof(text[0]), fp);
Reads probably 4 bytes of your file because sizeof(text[0]) is 1 and sizeof(text) is probably 4 (depending on pointer size). You need to use ftell() or some other means to get the actual size of your data file in order to read it all into memory.
Next, you are storing this information into a pointer that has no memory allocated to it. text needs to be malloc'd or made to hold memory in some way. This is probably what is causing your program to fail to work, just to start.
There are so so SO many further issues that it will take time to explain them:
How you are using strcpy to blow up memory when you place it intotempstr
How even if that weren't the case, it would copy probably the whole file at once, unless the file had NULL terminated strings within, which it may, so perhaps this is ok.
How you compare nwords[i].wordy, even though it is not initialized and therefore garbage.
How, even if your file were read into memory correctly, you look a pword, which is unitialized for your loop counter.
Please, get some help or ask your teacher about this because this code is seriously broken.
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;
}