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");
}
Related
I have a list of columns containing text but I just to fetch first upper row from this list. How to do that?
#include <stdio.h>
int main()
{
FILE *fr;
char c;
fr = fopen("prog.txt", "r");
while( c != EOF)
{
c = fgetc(fr); /* read from file*/
printf("%c",c); /* display on screen*/
}
fclose(fr);
return 0;
}
Your stop condition is EOF, everything will be read to the end of the file, what you need is to read till newline character is found, furthermore EOF (-1) should be compared with int type.
You'll need something like:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fr;
int c;
if(!(fr = fopen("prog.txt", "r"))){ //check file opening
perror("File error");
return EXIT_FAILURE;
}
while ((c = fgetc(fr)) != EOF && c != '\n')
{
printf("%c",c); /* display on screen*/
}
fclose(fr);
return EXIT_SUCCESS;
}
This is respecting your code reading the line char by char, you also have the library functions that allow you to read whole line, like fgets() for a portable piece of code, or getline() if you are not on Windows, alternatively download a portable version, and, of course you can make your own like this one or this one.
For whatever it's worth, here's an example that uses getline
#include <stdio.h>
int main()
{
FILE *fr;
char *line = NULL;
size_t len = 0;
ssize_t nread;
if (!(fr = fopen("prog.txt", "r"))) {
perror("Unable to open file");
return 1;
}
nread = getline(&line, &len, fr);
printf("line: %s, nread: %ld\n", line, nread);
fclose(fr);
return 0;
}
Some notes:
getline() can automatically allocate your read buffer, if you wish.
getline() returns the end of line delimiter. You can always strip it off, if you don't want it.
It's ALWAYS a good idea to check the status of I/O calls like "fopen()".
just replace EOF as '\n'(new line char). Than your code will read until reaching the new line. Here is what it looks like:
#include <stdio.h>
int main()
{
FILE *fr;
char c = ' ';
fr = fopen("prog.txt", "r");
while(c != EOF && c != '\n')
{
c = fgetc(fr); /* read from file*/
if(c != EOF){
printf("%c",c); /* display on screen*/
}
}
fclose(fr);
return 0;
}
I have not tested it yet but probably work. Please let me know if there is some problem with the code i will edit it.
Edit1:char c; in line 5 is initialized as ' ' for dealing with UB.
Edit2:adding condition (c != EOF) to while loop in line 7, for not giving reason to infinite loop.
Edit3:adding if statement to line 10 for not printing EOF which can be reason for odd results.
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.
I'm trying to get the HDD serial number from the following code & also trying to copy the lines from the "HDDserial.txt" to another text file called "Bond.txt":
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
char ch;
FILE *fp1,*fp2;
system("wmic path win32_physicalmedia get SerialNumber > HDDserial.txt");
fp1 = fopen("HDDserial.txt","r");
fp2 = fopen("Bond.txt","w");
while((ch= fgetc(fp1)!= EOF))
{
fputc(ch,fp2);
}
fputs("\nSender\n",fp2);
fclose(fp1);
fclose(fp2);
return 0;
}
I'm getting output of "HDDserial.txt" like this:
SerialNumber
32534230394a5a44303333333931202020202020
but my "Bond.txt" gives me some peculiar characters.like this image:
But I want the same output as "HDDserial.txt" in "Bond.txt" !
Can anyone please help me with my codes?so that I can fix this problem & get done proper copying?
!= binds tighter than =.
So this
ch = fgetc(fp1) != EOF
assigns the result of fgetc(fp1) != EOF to ch, which is 1 until EOF had been reached, which makes it 0.
To correct this use parentheses like this:
(ch = fgetc(fp1)) != EOF
Also fgetc() returns int not char. So make ch an int.
int main()
{
int ch;
...
while ((ch = fgetc(fp1)) != EOF)
{
fputc((char) ch, fp2);
}
...
Or introduce an intermediate variable:
int main()
{
int result;
...
while ((result = fgetc(fp1)) != EOF)
{
char ch = (char) result;
fputc(ch, fp2);
}
...
I was looking for a solution on how to read char by char on each line from a txt file and I found one, but I don't get some parts of the code. This is it:
#include <stdio.h>
#include <stdlib.h>
void handle_line(char *line) {
printf("%s", line);
}
int main(int argc, char *argv[]) {
int size = 1024, pos;
int c;
char *buffer = (char *)malloc(size);
FILE *f = fopen("myfile.txt", "r");
if(f) {
do { // read all lines in file
pos = 0;
do{ // read one line
c = fgetc(f);
if(c != EOF) buffer[pos++] = (char)c;
if(pos >= size - 1) { // increase buffer length - leave room for 0
size *=2;
buffer = (char*)realloc(buffer, size);
}
}while(c != EOF && c != '\n');
buffer[pos] = 0;
// line is now in buffer
handle_line(buffer);
} while(c != EOF);
fclose(f);
}
free(buffer);
return 0;
}
It was written by someone from here, but I can't reply 'cause I need more points lol. The parts I don't understand are:
if(c != EOF) buffer[pos++] = (char)c;
What does buffer[pos++] do? does it actually increase the variable "pos"? also, why does it start at 1 instead of 0? (pos starts at 0).
I can't really get track of the variable "pos", and I don't know why here buffer[pos] is 0:
buffer[pos] = 0;
The way I read the code is:
declare the size of the buffer that contains every char of every line (I mean, buffer is just free'd at the end, so it keeps the information on every line right?), then declare the other variables and alloc the memory of the buffer.
Open the file myfile.txt, and if it's not null, make pos = 0, then make "c" to store the first character of the file (now the function points to the next char), then if c != EOF meaning the end of file is not reached, save the character "c" in the position 1 of the buffer (I get confused here, why 1 and not 0). Then realloc twice as memory as before if needed. Do that for every character in the line untile you reach EOF or a \n. Now make buffer[pos] = 0, I dont know what value "pos" has, and I assume he makes buffer[pos] = 0 to indicate the end of the line? idk. Print the line, do that until you reach the end of the file. Close the file, free the memory on buffer.
Help! thanks.
fgetc(fp) - Reads the next character from the specified input stream (fp) and advances the associated file position indicator (you do not need to). If successful, the function will return the character read; otherwise, the value EOF (-1) is returned.
Here is a very simple example of using fgetc() to read each character of a file (and write it to another file using fputc())
char filename1[]={"c:\\play\\_in.txt"};//change paths as needed
char filename2[]={"c:\\play\\_out.txt"};
int main(void)
{
FILE *fp1 = {0};
FILE *fp2 = {0};
int c=0;
fp1 = fopen(filename1, "r");
if(fp1)
{
fp2 = fopen (filename2, "w");
if(fp2)
{
c = fgetc(fp1);
while(c != EOF)
{
fputc(c, fp2);
c = fgetc(fp1);
}
fclose(fp2);
}
fclose(fp1);
}
return 0;
}
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