go to a line and change to uppercase - c

I'm trying to do this assignment. Basically there's a file with 10 lines...using argv[] the user enters the filename in location 1 and line number is location 2 of the array.
I got everything working so far...checking file...counting line numbers and so on.
What would you guys suggest that I do to change the characters on that line to upper. I'm lost with how to do it. We can only use lseek, open, write, read and close commands.
My logic was ... if the user enters 5 for line number to change....in program I count the line numbers....when the counter hits 4..anything after that is line 5...up until \n.
The counter increments on each \n it comes across.
int line;
int counter = 0;
char c;
do
{
line = read(fd, &c, 1);
if (c == '\n')
{
counter++;
}
if (lnum == counter)
{
}
} while (line != 0);

You are just going to change the line, keeping it with the same size, so you can overwrite it(no need to rewrite the file). Since you have already found the way to read the lines you know the position where your line starts (in number of bytes, thanks to read function).
So you read the line you have to change to uppercase, you reposition the position indicator to the beginning of the line (using lseek) and then you rewrite the reading line with the changes you want.

Related

How to split text from file into words?

I'm trying to get the text from a file and split it into words by removing spaces and other symbols. This is part of my code for handling the file:
void addtext(char wordarray[M][N])
{
FILE *fileinput;
char word[N];
char filename[N];
char *pch;
int i=0;
printf("Input the name of the text file(ex \"test.txt\"):\n");
scanf("%19s", filename);
if ((fileinput = fopen(filename, "rt"))==NULL)
{
printf("cannot open file\n");
exit(EXIT_FAILURE);
}
fflush(stdin);
while (fgets(word, N, fileinput)!= NULL)
{
pch = strtok (word," ,'.`:-?");
while (pch != NULL)
{
strcpy(wordarray[i++], pch);
pch = strtok (NULL, " ,'.`:-?");
}
}
fclose(fileinput);
wordarray[i][0]='\0';
return ;
}
But here is the issue. When the text input from the file is:
Alice was beginning to get very tired of sitting by her sister on the bank.
Then the output when I try to print it is this:
Alice
was
beginning
to
get
very
tired
of
sitting
by
her
s
ister
on
the
bank
As you can see, the word "sister" is split into 2. This happens quite a few times when adding a bigger text file. What am I missing?
If you count the characters you'll see that s is the 57th character. 57 is 19 times 3 which is the number of parsed characters in each cycle, (20 -1, as fgets null terminates the string and leaves the 20th character in the buffer).
As you are reading lines in batches of 19 characters, the line will be cuted every multiple of 19 charater and the rest will be read by the next fgets in the cycle.
The first two times you where lucky enough that the line was cutted at a space, character 19 at the end of beggining, character 38 at the end of tired, the third time it was in the midle of sister so it cuted it in two words.
Two possible fixes:
Replace:
while (fgets(word, N, fileinput)!= NULL)
With:
while (fscanf(fileinput, %19s, word) == 1)
Provided that there are no words larger than 19 in the file, which is the case.
Make word large enough to take whole the line:
char word[80];
80 should be enough for the sample line.
What am I missing?
You are missing that a single fgets call at maximum will read N-1 characters from the file, Consequently the buffer word may contain only the first part of a word. For instance it seems that in your case the s from the word sister was read by one fgets call and that the remaining part, i.e. ister was read by the next fgets call. Consequently, your code detected sister as two words.
So you need to add code that can check whether the end of the is a whole word or a part of a word.
To start with you can increase N to a higher number but to make it work in general you must add code that checks the end of the word buffer.
Also notice that long words may require more than 2 fgets call.
As a simple alternative to fgets and strtok consider fread and a simple char-by-char passing of the input.
Below is a simple, low-performance example of how it can be done.
int isdelim(char c)
{
if (c == '\n') return 1;
if (c == ' ') return 1;
if (c == '.') return 1;
return 0;
}
void addtext(void)
{
FILE *fileinput;
char *filename = "test.txt";
if ((fileinput = fopen(filename, "rt"))==NULL)
{
printf("cannot open file\n");
return;
}
char c;
int state = LOOK_FOR_WORD;
while (fread(&c, 1, 1, fileinput) == 1)
{
if (state == LOOK_FOR_WORD)
{
if (isdelim(c))
{
// Nothing to do.. keep looking for next word
}
else
{
// A new word starts
putchar(c);
state = READING_WORD;
}
}
else
{
if (isdelim(c))
{
// Current word ended
putchar('\n');
state = LOOK_FOR_WORD;
}
else
{
// Current word continues
putchar(c);
}
}
}
fclose(fileinput);
return ;
}
To keep the code simple it prints the words using putchar instead of saving them in an array but that is quite easy to change.
Further, the code only reads one char at the time from the file. Again it's quit easy to change the code and read bigger chunks from the file.
Likewise you can add more delimiters to isdelim as you like (and improve the implementation)

Remove empty new line at the end of a file

I have a file that's storing strings from the user's input (stdin)
However there are 2 situations
If I read it normally, my file will have an empty line at its end due to the newline from the last string the user introduced.
If I remove the \n from the input string, the file stores all strings in the same line, which is not wanted.
How can I simply remove that newline from the end of the file?
I can edit and provide some of my code if required.
EDIT: Let's say the last line of a file I already have is "cards"
when the cursor is in front of "cards", if I press the down arrow it doesn't go on to the next line, while in this case it can happen once.
For my code to function perfectly I can't let that happen,
Here's an example of what I have:
f=fopen(somefile, "w");
do
{
fgets(hobby, 50, stdin);
fprintf(f, "%s", hobby)
} while(strcmp(hobby,"\n") != 0);
The newline character1 at the end of the file is part of the last line. Removing it is possible but makes the last line incomplete, which will break many programs. For example, concatenating another file at the end of this file will cause the last line to be merged with the first line of the concatenated file.
A Yuri Laguardia commented, if you later reopen this file in append mode to write more lines, the first one added would be concatenated at the end of this last incomplete line. Probably not the intended behavior.
If you do not want the file to contain empty lines, check user input before writing the line into the file:
void input_file_contents(FILE *fp) {
char userinput[80];
printf("enter file contents:\n");
while (fgets(userinput, sizeof userinput, stdin)) {
if (*userinput != '\n') {
fputs(userinput, fp);
}
}
}
EDIT:
Your code does not test for termination at the right place: you write the empty line before the test. Do not use a do / while loop:
f = fopen(somefile, "w");
if (f != NULL) {
/* read lines until end of file or empty line */
while (fgets(hobby, 50, stdin) != NULL && *hobby != '\n') {
fputs(hobby, f);
}
}
1 The newline character is actually a pair of bytes <CR><LF> on legacy systems.

Reading lines ahead in a file (In C)

I have a file that looks like this:
This is the first line in the file
This is the third line in the file
Where I have a blank line in the file (On line 2). I want to read the file line by line (Which I do using fgets), but then i want to read ahead just check if a line there is a blank line in the file.
However, My while fgetshas a break statement in it, because my function is only so posed to read the file a line at a time per function call.
so if I call the function:
func(file);
It would read the first line, then break.
If I called it again, it would read the second line then break, etc.
Because I have to implement it this way, it's hard to read ahead, is there any way I can accomplish this?
This is my code:
int main(void) {
FILE * file;
if(file == NULL){perror("test.txt"); return EXIT_FAILURE;}
readALine(file);
}
void readALine(FILE * file) {
char buffer[1000];
while(fgets(buffer,sizeof(buffer),file) != NULL) {
//Read lines ahead to check if there is a line
//which is blank
break; //only read a line each FUNCTION CALL
}
}
So to clarify, if I WAS reading the entire file at once (Only one function call) it would go like this (Which is easy to implement).
int main(void) {
FILE * file = fopen("test.txt","r");
if(file == NULL){perror("test.txt"); return EXIT_FAILURE;}
readALine(file);
}
void readALine(FILE * file) {
char buffer[1000];
while(fgets(buffer,sizeof(buffer),file) != NULL) {
if(isspace(buffer[0]) {
printf("Blank line found\n");
}
}
}
But since I'm reading the file in (Line by line, per function call), The second piece of code above wouldn’t work (Since I break per line read, which I can't change).
Is there a way I could use fseek to accomplish this?
A while loop ending in an unconditional break is an if statement, so I don't really see why you are using a while loop. I'm also assuming you are not worried about a single line being longer than 1000 chars.
the continue statement jumps over to the next iteration of the loop and checks the condition again.
void readALine(FILE * file) {
char buffer[1000];
while(fgets(buffer,sizeof(buffer),file) != NULL) {
if(!isspace(buffer[0]) { //note the not operator
//I'm guessing isspace checks for a newline character since otherwise this will be true also for lines beginning with space
continue; //run the same loop again
}
break;
}
//buffer contains the next line except for empty ones here...
}
You can "read ahead" by simply storing your position in the file (with position = ftell(your_file)), then read the line, if this is a blank line do whatever you have to do, and finally go back to the position you were (with fseek(your_file, position, SEEK_SET)).
Hope this helps !
The while loop in readALine reads lines until the end of the file. So it will skip blank lines, and all other lines.
You can return from within the loop if you've found a non-blank line:
while(fgets(buffer,sizeof(buffer),file) != NULL) {
if (buffer[0] != '\n')
return;
}
If you also want to skip lines that consist of nothing but spaces, you can write a function that does that check:
bool isNothingButWhitespace(char *s) {
while (*s == ' ' || *s == '\n')
s++;
return *s == '\0';
}
This will find the first character that's not whitespace. If it's the string terminator '\0' then it will return true (the string was nothing but whitespace) otherwise falseS (there was some non-whitespace character found).
If the while loop in readALine completes due to it reaching the end of file, you need some way to signal that back to the caller. I recommend setting buffer[0] = '\0'.

Any way to signal an end-of-file without creating a new line in command line/bash?

I am writing a quick little C program to count up the number of words entered via standard input and give a count of the words entered as well as the average words per line. The following code works fine for files, but when entering input into the command line, I can (seemingly) only signal an EOF (Ctrl-Z since I'm on Windows) on a new line, which throws off the line count. Is there any way to remedy this? Here are some examples:
The program:
#include<stdio.h>
main()
{
int lines = 0, totalCount = 0;
float average = 0.0;
char newline= ' ';
// scanf and throw away the string values
while (scanf("%*s%c", &newline) != EOF)
{
// at least one line exists
if (totalCount == 0)
{
lines++;
}
// update count
totalCount++;
// account for any subsequent lines
if (newline == '\n')
{
lines++;
}
}
average = (float) totalCount / lines;
printf("%d ", totalCount);
printf("%.2f\n", average);
}
This works fine (the file has 313 words and 35 lines):
a.exe < testfile.txt
313 8.94
This does not, however:
a.exe
This is a test
to see if this
works
okay
^Z
10 2.00
The end of file adds one line to make 5 lines in total, making the average words per line come out to 2.00. Is there any way to remedy this or is that just the way it has to be?
An update for anyone else looking for this solution:
On the Linux/Unix shell, one can enter the EOF twice on the same line to flush the line buffer and create and EOF on the same line as such:
This is my text and now I will flush the buffer and signal EOF on the same line ^D^D
However, this method does not seem to work on the Windows command line, so I am still searching there. I will edit if I get an update.
EDIT: Using the method above throws off the input if you do not add a space in between the last character of the line and the EOF sentinel.

C Program unable to create output text file

A friend of mine needs to use MATLAB for one of his classes, so he called me up (a Computer Science Major) and asked if I could teach him C. I am familiar with C++, so I am also familiar with the general syntax, but had to read up on the IO library for C.
I was creating some simple IO programs to show my friend, but my third program is causing me trouble. When I run the program on my machine using Eclipse (with the CDT) Eclipse's console produces a glitchy output where instead of prompting me for the data, it gets the input and then prints it all at once with FAILURE.
The program is supposed to get a filename from user, create the file, and write to it until the user enters a blank line.
When I compile/run it on my machine via console (g++ files2.c) I am prompted for the data properly, but FAILURE shows up, and there is no output file.
I think the error lies with how I am using the char arrays, since using scanf to get the filename will create a functional file (probably since it ignores whitespace), but not enter the while loop.
#include <stdio.h>
#define name_length 20
#define line_size 80
int main() {
FILE * write_file; // pointer to file you will write to
char filename[name_length]; // variable to hold the name of file
char string_buffer[line_size]; // buffer to hold your text
printf("Filename: "); // prompt for filename
fgets(filename, name_length, stdin); // get filename from user
if (filename[name_length-1] == '\n') // if last char in stream is newline,
{filename[name_length-1] = '\0';} // remove it
write_file = fopen(filename, "w"); // create/overwrite file user named
if (!write_file) {printf("FAILURE");} // failed to create FILE *
// inform user how to exit
printf("To exit, enter a blank line (no spaces)\n");
// while getting input, print to file
while (fgets(string_buffer, line_size, stdin) != NULL) {
fputs(string_buffer, write_file);
if (string_buffer[0] == '\n') {break;}
}
fclose(write_file);
return 0;
}
How should I go about fixing the program? I have found next to nothing on user-terminated input being written to file.
Now if you will excuse me, I have a couple of files to delete off of my University's UNIX server, and I cannot specify them by name since they were created with convoluted filenames...
EDIT------
Like I said, I was able to use
scanf("%s", filename);
to get a working filename (without the newline char). But regardless of if I use scanf or fgets for my while loop, if I use them in conjunction with scanf for the filename, I am not able to write anything to file, as it does not enter the while loop.
How should I restructure my writing to file and my while loop?
Your check for the newline is wrong; you're looking at the last character in filename but it may be before that if the user enters a filename that's shorter than the maximum. You're then trying to open a file that has a newline in it's name.
These lines seem to be incorrect:
if (filename[name_length-1] == '\n') // if last char in stream is newline,
{filename[name_length-1] = '\0';} // remove it
You verify the name_length - 1 character,, which is 19 in your case without any regard of the introduced filename's length. So if your file name's length is less then 18 you won't replace the '\n' character at the end of your string. Obviously the file name can't contain '\n' character.
You need to get the size of you file name first with strlen() as an example.
if (filename[strlen(filename) - 1] == '\n')
{
filename[strlen(filename) - 1] = '\0';
}
(Don't forget to include the string.h header)
I hope I was able to help with my weak english.

Resources