How does following statement produce spaces? - c

What my program "upper" trying to do is making letters upper case. It gets a file from the commmand line as argv; then reads it afterwards it makes them uppercase.
An example: "i wonder if it works" in the example.txt file. In command line:
C:\Users\...>upper example.txt
I WONDER IF IT WORKS
This was the code I used first:
int main (int argc, char *argv[]){
FILE * fp;
int ch;
if ((fp = fopen (argv[1] , "r+")) == NULL) {
fprintf (stderr , "Can not be opened.");
exit(EXIT_FAILURE);
}
while((ch = getc(fp)) != EOF){
if (isalpha(ch))
putchar(toupper(ch));
else
putchar(' ');
}
fclose(fp);
return 0;
}
It works but I saw a more concise version which doesn't need the else statement.
while((ch = getc(fp)) != EOF){
putchar(toupper(ch));
}
And it puts the spaces between each word too. How is this possible?

From the documentation
int toupper(int c);
Converts c to its uppercase equivalent if c is a lowercase letter and has an uppercase equivalent. If no such conversion is possible, the value returned is c unchanged.

Related

In C, "getc" reads only three lines from text file

My Code is HERE
int main(){
FILE *fp;
fp = fopen("dic.txt", "r");
while(getc(fp) != EOF){
if(getc(fp) == ' '){
printf("up ");
}
}
}
My dic.txt is HERE
dic.txt
my predict is that "up up up up "
because, there are four space " "
but it printed "up " only one
what is problem?
You are calling getc twice per iteration of the loop; one of these two calls compares the character to EOF, while the other call compares the character to ' '.
This has two consequences:
Your program will only print "up" for the spaces which are on even position, and will miss all spaces which are on odd position;
Your program might make one extra call to getc after reaching EOF the first time.
How to fix
You need to make a single call to getc per iteration of the loop. Save the character returned by getc to a local variable; then use this variable to check for spaces in the body of the loop, and to check for EOF in the condition of the loop.
You want this:
#include <stdio.h>
int main() {
FILE* fp;
fp = fopen("dic.txt", "r");
if (fp == NULL)
{
printf("Can't open file\n");
return 1;
}
int ch; // int is needed her, not char !!
while ((ch = getc(fp)) != EOF) { // read one char and check if it's EOF in one go
if (ch == ' ') {
printf("up ");
}
}
}
You need to call getc once only in the loop, otherwise you skip one out of two characters.
Bonus: you need to check if fopen fails.
Try Out This Code:
FILE *fp;
fp = fopen("dic.txt", "r");
int ch = getc(fp);
while(ch != EOF){
if(getc(fp) == ' '){
printf("up ");
}
}
return 0;

the function "fgetc ()" does not work properly in a While

I wrote a little program that is supposed to read the contents of a file character by character but what the code does is that it jumps each time a character as if it escapes a caracters each time and I don't understand why
and i dont know what to do
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i, age = 18;
char strind[] = "Himou";
FILE *file = NULL;
file = fopen("test.txt", "r+");
if(file != NULL)
{
do
{
printf("%c", fgetc(file));
}while(fgetc(file) != EOF);
fclose(file);
}
else
{
printf("the file couldn't be open");
}
return 0;
}
the file exists and contains "Hello World !!Your name is Himou and your age is 18", so thats what i expected but the actual result "HloWrd!Yu aei io n oraei 8"
it jumps each time a character as if it escapes a caracters each time
do
{
printf("%c", fgetc(file)); <<< here you read and print a character
}while(fgetc(file) != EOF); << here you read again a character and lost it
yes this is true, because you ask for that, see comments I added in the code above
i dont know what to do
probably you want something like that to write all the read characters :
int c;
while ((c = fgetc(file)) != EOF)
putchar(c);

Opening File byte by byte printing in hex

C programmer newcomer here.
I'm trying to open a .obj file (containing LC3 instructions) and print them in groups of 2 bytes line by line in hex. I've tried opening the file and iterating through char by char and printing in hex but I am unsure how to group the bytes together in groups of 2 to print them together. I am also printing out a group of "fffffff"s for the bytes that lead with a 1 (I assume).
void readFile(const char *fileName) {
FILE *file;
file = fopen(fileName, "rb");
char ch;
while ((ch = fgetc(file)) != EOF) {
if (isprint(ch)) {
printf("%x", ch);
}
else {
printf("%02x", ch);
if (ch == '\n') {
fputs("\n", stdout);
}
}
}
fclose(file);
}
The output I am looking to achieve is:
0x4500
0x2009
0xe209
0xa409
But I am getting:
0x45
0020
09fffffffe209fffffffa40956
I understand that the hex is printing the excess "ffffffff"s due to not being an unsigned char but I am struggling to print close to the desired output. Any help in printing in 2 byte groups or how to remove the "fffffff"s would be greatly appreciated, and I'm really struggling.
The getchar()
family of functions (including getc() and fgetc()) all behave similarly; they return an int, not a char. Read the values into an int and live life happy.
void readFile(const char *fileName)
{
FILE *file = fopen(fileName, "rb");
if (file == 0)
return;
int ch;
while ((ch = fgetc(file)) != EOF)
{
printf("0x%.2x", ch);
if ((ch = fgetc(file)) == EOF)
break;
printf("%.2x\n", ch);
}
putchar('\n');
fclose(file);
}
If there's an even number of bytes in the file, you'll get an extra newline at the end. If that's a problem, keep a record of whether you exit the loop at the top (no newline needed) or from the middle (newline needed).
Both isprint(ch) and ch == '\n' have absolutely nothing to do with 2-byte grouping.
Perhaps you want something simple like this:
unsigned char ch;
while ((ch = (unsigned char)fgetc(file)) != EOF) {
printf("0x%02x", ch);
if ((ch = (unsigned char)fgetc(file)) != EOF)
printf("%02x", ch);
printf("\n");
}

Word Count, Segmentation Fault - C

I'm trying to run a program that finds the word count for a file. Every time I compile the program it gives me a Segmentation Fault(Core Dumped). Can't figure out why.
#include <stdio.h>
int main(int argc, char* argv[]){
int wc = 1;
FILE *input = fopen(argv[1],"r");
char c = fgetc(input);
while(c != EOF){
if(c == ' '){
wc++;
}
else
c = fgetc(input);
}
fclose(input);
printf("Word Count = %d", wc);
return 0;
}
You're probably segfaulting because you're not passing in a file name on the command line. When you do that, argv[1] is NULL, so fopen is dereferencing a NULL pointer.
You pass the file name to your program on the command line like this:
./my_program file_to_test
To prevent the core dump, you should check that an argument was passed in by checking the value of argc. You should also check the return value of fopen to ensure the file was opened:
if (argc < 2) {
printf("no file name given");
exit(1);
}
FILE *input = fopen(argv[1],"r");
if (input == NULL) {
perror("fopen failed");
exit(1);
}
Then you have another problem:
if(c == ' '){
wc++;
}
else
c = fgetc(input);
When you find a space character, you don't attempt to read the next character. So c doesn't change once a space is read, leading to an infinite loop.
You need to get rid of the else and always call fgetc:
if(c == ' '){
wc++;
}
c = fgetc(input);
Also, the fgetc function returns an int (actually an unsigned char cast to an int), so you should declare c as an int. Otherwise, checking it against EOF can fail.

Counting number of words with multiple whitespaces

I am trying to write a program that prints the number of words found in a text file. Words are defined as sequences of characters separated by any number of white space.
However, I am having a problem when there are multiple whitespaces because then it doesn't report the right number of words.
Here is my code so far:
#include <stdio.h>
int main()
{
FILE *fp;
char str;
int i=0;
/* opening file for reading */
fp = fopen("myfile.txt" , "r");
if(fp == NULL) {
perror("Error opening file");
return(-1);
}
while(( str = fgetc(fp)) != EOF ) {
if (str == ' ')
++i;
}
printf("%d\n", i);
fclose(fp);
return(0);
}
myfile.txt is:
Let's do this! You can do it. Believe in yourself.
I'm not sure if I use fgets, fscanf, or fgetc.
Let's say I define whitespace as it is defined in the fscanf function when reading a string
It prints 14 which is not right. I'm not sure how to account for multiple whitespaces. In this case, whitespaces are any number of spaces between words.
Counting a whitespace only if it is not preceded by any other white space will do the trick.
#include <stdio.h>
int main()
{
FILE *fp;
char str;
char prevchar; //tracks the previous character
int i=0;
/* opening file for reading */
fp = fopen("myfile.txt" , "r");
if(fp == NULL) {
perror("Error opening file");
return(-1);
}
prevchar='x'; //initialize prevchar to anything except a space
while(( str = fgetc(fp)) != EOF ) {
if (str == ' ' && prevchar!=' ') // update the count only if previous character encountered was not a space
++i;
prevchar=str;
}
printf("%d\n", i+1);
fclose(fp);
return(0);
}
Edit: The code assumes that words are separated by one or more spaces and does not cover all the corner cases like when sentences spread over multiple lines or when words are separated by comma and not spaces. But these cases can be covered by adding more conditions.
just use a little state diagram, two cases are, either you are inside a word, or you are outside a word
#include <stdio.h>
int main()
{
FILE *fp;
char str;
int i=0,inside_word =0;
/* opening file for reading */
fp = fopen("myfile.txt" , "r");
if(fp == NULL) {
perror("Error opening file");
return(-1);
}
inside_word =0;
while(( str = fgetc(fp)) != EOF ) {
if (str == ' ' || str == '\n' || str == '\t')
inside_word = 0;
else if(inside_word == 0){
i++;
inside_word=1;
}
}
printf("%d\n", i);
fclose(fp);
return(0);
}
First thing comes into my mind is, add another while loop right after ++i to exhaust space characters.
And by the way, be careful with your terminology, you are not dealing with whitespaces you are just taking care of space characters. \t and \n are also whitespaces!
How about using regular expression such as '!\s+!' to replace with a single space ' ', then continue with your code

Resources