how to read specific line read from file - c

I have managed to read all the lines in my file to a char array but when I want to read a specific line i.e. line 254 as in the example below, I always get the data in the last line in my file. Any idea what's the problem. Thank you.
Here is sample of the code:
while (fgets(line,2000,fp)!=NULL
{
readData [n] = line;
n++;
}
printf ("print line after %s\n",readData [254]);

You're copying the pointer every time. So at the end every entry of the readData array will point to the same memory. Try to copy the data instead:
readData[n] = strdup(line);
And remember to free when done. If you don't have strdup or don't want to use it:
readData[n] = malloc(strlen(line) + 1);
strcpy(readData[n], line);

I'm guessing "readData" is an array of char*s, so when you say readData[n] = line you are always setting the array to the same "buffer" of data.
You need something a bit more like
char buffer[numLines][colsPerLine];
char line[colsPerLine];
while (fgets(line,2000,fp)!=NULL
{
strcpy(buffer[n], line); // copy contents of line into the buffer
n++;
}
printf ("print line after %s\n",buffer[254]);

You can use seek pointer to move cursor to line no . And then apply reading line .
Hope it will work.

Related

C: Store strings created by getline() in a Linked list?

I need to do my own implementation of grep in C. I'm using getline() to read from the file (This being specified by the user, if not, it reads from stdin).
char* line = NULL;
size_t size = 0;
int q = 101; //Prime number for Rabin-Karp Algorithm
bool coincidence;
list_t* list = list_create();
while((getline(&line, &size, file)) > 0 && list) {
list_insert_end(list, line);
if (list_length(list) > n + 1) list_erase_first(list);
coincidence = search(string, line, q);
if (coincidence){
while (!list_is_empty(list)) printf("%s", (char*) list_erase_first(list));
}
}
free(line);
That's the code I have now. I create a char* line, which will be replaced by the string received by getline(). Then I try to store a copy of it in a list (Or queue), however, whenever I use getline again, all the copies I made will be replaced.
I need to save the copies of the previous n lines before finding a coincidence, and when I do, I have to print them. I thought of using strdup, but it would have the same results.
I thought of using an array, but I couldn't come up with the right implementation, since I cannot store all the lines in memory, so when I reach n + 1 read lines without a coincidence, I have to erase and replace the first one that was stored. A queue or list would make it so much easier, but I'm unable to save the copies of getline properly.
Once you have stored line into the list (as in the list is storing the pointer value), just set line = NULL; so that the next time you hit getline() a new line will be allocated.

Storing strings in array in C

I have read a lot of questions on this, and using them I have altered my code and have created code which I thought would work.
I think it's my understanding of C, which is failing me here as I can't see where I'm going wrong.
I get no compilation errors, but when I run i receive 'FileReader.exe has stopped working' from the command prompt.
My code is :
void storeFile(){
int i = 0;
char allWords [45440][25];
FILE *fp = fopen("fileToOpen.txt", "r");
while (i <= 45440){
char buffer[25];
fgets(buffer, 25, fp);
printf("The word read into buffer is : %s",buffer);
strcpy(allWords[i], buffer);
printf("The word in allWords[%d] is : %s", i, allWords[i]);
//allWords[i][strlen(allWords[i])-1] = '\0';
i = i + 1;
}
fclose(fp);
}
There are 45440 lines in the file, and no words longer than 25 char's in length. I'm trying to read each word into a char array named buffer, then store that buffer in an array of char arrays named allWords.
I am trying to get this part working, before I refactor to return the array to the main method (which I feel won't be a fun experience).
You are trying to allocate more than a megabyte (45440*25) worth of data in automatic storage. On many architectures this results in stack overflow before your file-reading code even gets to run.
You can work around this problem by allocating allWords statically, like this
static char allWords [45440][25];
or dynamically, like this:
char (*allWords)[25] = malloc(45440 * sizeof(*allWords));
Note that using buffer in the call to fgets is not required, because allWords[i] can be used instead, without strcpy:
fgets(allWords[i], sizeof(*allWords)-1, fp);
Also note that an assumption about file size is unnecessary: you can continue calling fgets until it returns NULL; this indicates that the end of the file has been reached, so you can exit the loop using break.

New to C, trying to better understand char arrays, pointers, reading in files, etc

Alright, so I am working on linux and emacs for the first time using C, and coming from pretty beginner level java programming in eclipse, my new CS course is really daunting. SO much stuff has been thrown at me as if I already knew it...
Anyway, the current part of my assignment I am working on involves reading in text from a file (doing that by piping a text file as standard input into my program). Currently I had three functions, a main function where I read in the file / call other functions, a function that reverses the order of a single word (apple becomes elppa) with *char beg and *char end as parameters, and a function that reverses the order of every word in a line of words, calling the previous function and taking a char *str as a parameter.
I am having trouble reading in the files in my main method in a way that makes it easy to utilize these functions. Here's a snippet of how I am reading them in currently, but as you can see I haven't figured out a way to store a line of words and send that into my function (I need to reverse line by line, so I can't just add every single char to one long array)
enter code here``
char line[8192]
int location = 0;
FILE *in = stdin;
int buff = 0;
while (buff = fgetc(in))
{
fprintf(stderr, "Character is: %d '%c' \n", buff, (char)buff);
if (buff == EOF)
{
break;
}
line[location] = (char)buff;
location++;
}
line[location] = '\0';
If you want to get a whole line, you can do this:
char line[MAX_LINE_SIZE];
fscanf(in, "%[^\n]", line);
//do whatever you need with the line
fscanf(in, "%[\n]", line);
The first fscanf call reads a whole line and store in variable line.
But it doesn't skip that line! If you use it again, it will store the very same line.
The second fscanf call is for this: it stores '\n' in variable line and skips the line you read previously.
If you want, you can create another buffer to get the '\n' and skip the line:
char garbage[2];
fscanf(in, "%[\n]", garbage);
I hope this helps.

Using fgets() in file parsing

I have a file which contains several lines.
I am tokenizing the file, and if the token contains contains .word, I would like to store the rest of the line in c-string.
So if:
array: .word 0:10
I would like to store 0:10 in a c-string.
I am doing the following:
if (strstr(token, ".word")) {
char data_line[MAX_LINE_LENGTH + 1];
int word_ret = fgets(data_line, MAX_LINE_LENGTH, fptr);
printf(".word is %s\n", data_line);
}
The problem with this is that fgets() grabs the next line. How would I grab the remainder of the current line? Is that possible?
Thank you,
strstr() returns a pointer to where the first character of ":word" is found.
This means that if you add the length of ":word" (5 characters) to that, you will get a pointer to the characters after ":word", which is the string you want.
char *x = strstr(token, ".word");
char *string_wanted = x + 5;
First of all it is obvious that you need to use fgets only once for every line you parse and then work with a buffer where the line is stored.
Next having a whole line you have several choices: if the string format is fixed (something like " .word") then you may use the result of "strstr" function to locate the start of ".word", advance 6 characters (including space) from it and print the required word from the found position.
Another option is more complex but in fact is a liitle bit better. It is using "strtok" function.
You need to have already read the input into a buffer, which I'm assuming is token, and from there you just copy from the return value of strstr + the length of ".word" to the end of the buffer. This is what I'd do:
char *location = strstr(token, ".word");
if (location != NULL) {
char data_line[MAX_LINE_LENGTH];
strncpy(data_line, location + 5, MAX_LINE_LENGTH);
printf(".word is %s\n", data_line);
}
You could add 5 or 6 to the pointer location (depending on whether or not there's going to be a space after ".word") to get the rest of the line.
Also note that the size parameter in strncpy and fgets includes space for the terminating NUL character.

string replace in file using C

I haven't yet implemented this, I'm still in the thinking stage, but I have to go through a file and replace a certain string with another string. For example,
<img src="/images/logo.gif" ...
should become
<img src="/proxy/www.example.com/images/logo.gif" ...
Any advice on how I can approach this? Perhaps there exist some "string replace" C functions that would do this for me that I don't know about...?
Right now, if I had to write this function myself, I would give it as parameters the file, string to replace, replacement string. Then I would manually go through the file and look for an occurrence of the string and recreate it. This, however, seems very inefficient. Are there better ways to do this?
Thanks,
Hristo
No, there is no function in C that replaces a string throughout a file. You must implement it yourself.
That said, what you're showing us is HTML, and HTML is tricky, because it's hierarchical. Are you required to correctly parse it? Because if you are, the task is much more difficult. Seeing that it's homework, I doubt it, so you might do enough by:
open the file and load it to memory (assuming it isn't too large - if it is, you can write into a temporary file and move it onto the original one after you've finished)
continuously use strstr to find the anchor string you need to start replacing
replace
repeat 2 and 3 until finished with file
write file back
Since it's homework I'm going with the assumption that the string can not span multiple lines. If this assumption is correct (and barring the complications with "replacing text in HTML") then:
1 Read the next line
2 Replace string and write line (to another file)
3 If not at end, goto #1
4 Win \o/
Or perhaps the teacher wants something else shrug
First of all, C is an awesome language, but is one of the most painful languages to do this type of operation in. Just had to say it.
Can you safely assume that the contents of the entire file can fit in memory? If so:
allocate buffer big enough to hold file contents
read entire file into buffer
inputPtr = 0
while(inputPtr < size of buffer) {
replacePosition = strstr(inputPtr, stringToReplace);
if (replacePosition != NULL)
writeUntil = replacePosition - 1
else
writeUntil = end of buffer
write out buffer from inputPtr to writeUntil inclusive (could be 0 bytes)
if (replacePosition == NULL) break
write out the replacement string
inputPtr = replacePosition + strlen(stringToReplace)
}
Since this is homework, I won't give you an answer but I'll point out a classic issue that trips people up.
In C, it's easiest to read a fixed byte count (you can try to do line by line but if a line is too long, that reverts to reading a fixed number of bytes). If the string you are trying to replace ends up getting split between one buffer and a second buffer:
buf1 -> "...<img src=\"/ima"
buf2 -> "ges/logo.gif\"..."
you won't be able to do a simple search replace in memory.
Are you try strcpy function for this,
Assign the url in one string and replace it by strcpy function.
You should investigate the sed command. See what it does and do something similar.
It works as a filter, so when using it to replace something in a file what you often do is capture the output into a file and then replace the old file with the new file.
You can use following program to search & replace string in a file.
int main()
{
.....
replaceIPAddress( "System.cfg", "172.16.116.157", "127.0.0.1");
.....
}
void replaceIPAddress( char * confFileName, char *text_to_find , char *text_to_replace )
{
FILE *input = fopen(confFileName, "r");
FILE *output = fopen("temp.txt", "w");
char buffer[512];
while (fgets(buffer, sizeof(buffer), input) != NULL)
{
char *pos = strstr(buffer, text_to_find);
if (pos != NULL)
{
/* Allocate memory for temporary buffer */
char *temp = calloc(
strlen(buffer) - strlen(text_to_find) + strlen(text_to_replace) + 1, 1);
/* Copy the text before the text to replace */
memcpy(temp, buffer, pos - buffer);
/* Copy in the replacement text */
memcpy(temp + (pos - buffer), text_to_replace, strlen(text_to_replace));
/* Copy the remaining text from after the replace text */
memcpy(temp + (pos - buffer) + strlen(text_to_replace),
pos + strlen(text_to_find),
1 + strlen(buffer) - ((pos - buffer) + strlen(text_to_find)));
fputs(temp, output);
free(temp);
}
else
fputs(buffer, output);
}
fclose(output);
fclose(input);
/* Rename the temporary file to the original file */
rename("temp.txt", confFileName);
}

Resources