The first piece of code prints each line in b.txt in a new line when it outputs it, and the second code is the conversion from hexadecimal to decimal. I am bad at writing big programs, so I split the task and write smaller programs instead. I am having trouble combining these two programs. Can anyone help ?
#include <stdio.h>
int main ( int argc, char **argv )
{
FILE *fp = fopen ( "b", "r");
char line[1024];
int ch = getc ( fp );
int index = 0;
while ( ch != EOF ) {
if ( ch != '\n'){
line[index++] = ch;
}else {
line[index] = '\0';
index = 0;
printf ( "%d\n", line );
}
ch = getc ( fp );
}
fclose ( fp );
return 0;
}
This is the second program
#include <stdio.h>
#include <stdlib.h>
int main()
{
unsigned int d;
FILE *fp;
FILE *ptr_file;
fp = fopen("normal_data","r"); // read mode
ptr_file =fopen("normal_decimal", "w");
while(fscanf(fp,"%x", &d) == 1)
{
fprintf(ptr_file, "%d /n", d);
}
while( ( d = fgetc(fp) ) != EOF )
fclose(fp);
return 0;
}
It is good programming practice to split your program in small related fragments.
But instead of using a main function everywhere , try making functions which accomplish certain tasks and add them to a header file.
This will make it much easier to write, debug and re-use the code.
In the above case, converting hexadecimal to decimal is clearly something which maybe used again and again.
So, just make a function int hex_to_dec(char* input); which takes a string of input e.g,"3b8c" and converts it to a decimal and returns the converted value.
You may also want to make function void printFile(FILE* fp); which takes the pointer to a file and prints it data to stdout.
You can add these and other functions you have made, to a header file like myFunctions.h and then include the file into whatever program you need to use your functions in.
Related
prefacing by saying, I've lurked in Stackoverflow and this is my first Question, but thank you all you kind souls for your contributions!
I am trying to write comments and classes from a .java file to a .txt file using C programming. I used the fgetc and fputc functions to do this and managed to write the whole file across, but when I try to communicate that I only want the comments right up to the class (so before the "{" and everything after the "}") it seems to not print anything. I am quite new to C and just a bit stuck. I have included my code below, any help would be super appreciated. Sorry if this is hard to understand, I am not natively English speaking.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
FILE *input = fopen("text.java", "r"); //opens file
FILE *comments = fopen("comments.txt", "w");
char ch;
ch = fgetc(input);
while(ch != EOF)
{
while(!strcmp(ch, "{"))
{
fputc(ch, comments);
ch = fgetc(input);
}
ch = fgetc(input);
}
fclose(input);
fclose(comments);
return 0;
}
As already pointed out in the comments section by someone else, your code has the following errors:
The return type of fgetc is int, not char. The value EOF cannot be represented in char, so you should not truncate the int return value to char. Instead, you should declare ch as an int.
The function strcmp is for comparing strings, not characters.
When calling fgetc in your inner loop, you are not checking the return value for EOF.
Also, your algorithm for solving the problem does not seem correct.
One way to solve the problem is for your program to always remember whether it is inside a brace or not, and to act accordingly. For example, you can declare a bool inside_brace variable which always specifies whether you are inside a brace or not, like this:
#include <stdio.h>
#include <stdlib.h>
//the following line is necessary for the "bool" data type
#include <stdbool.h>
int main( int argc, char **argv )
{
FILE *input = fopen("text.java", "r");
FILE *comments = fopen("comments.txt", "w");
int ch;
bool inside_brace = false;
while ( ( ch = fgetc(input) ) != EOF )
{
if ( !inside_brace )
{
if ( ch == '{' )
{
inside_brace = true;
continue;
}
fputc( ch, comments );
}
else //inside a brace
{
if ( ch == '}' )
{
inside_brace = false;
continue;
}
}
}
fclose(input);
fclose(comments);
return EXIT_SUCCESS;
}
Note that this solution will only work if you only have one nesting level of braces, i.e. that you don't have one { inside another { without first closing the first { with a }. If it is possible that you have more than one level of nesting, then the variable bool inside_brace will not be sufficient. Instead, you will need a counter to keep track of the current nesting level, for example like this:
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char **argv )
{
FILE *input = fopen("text.java", "r");
FILE *comments = fopen("comments.txt", "w");
int ch;
int nesting_level = 0;
while ( ( ch = fgetc(input) ) != EOF )
{
switch ( ch )
{
case '{':
nesting_level++;
continue;
case '}':
nesting_level--;
if ( nesting_level < 0 )
{
fprintf( stderr, "Error: Negative nesting level encountered!\n" );
return EXIT_FAILURE;
}
continue;
}
if ( nesting_level == 0 )
fputc( ch, comments );
}
}
fclose(input);
fclose(comments);
return EXIT_SUCCESS;
}
So I am writing a program in C that takes in a few command-line arguments and also reads a file and prints it to standard out. This is my code thus far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( int argc, char* argv[] ) {
char* file_path;
float a;
float b;
char filedata[200];
if (argc != 4) {
printf("Error: 4 arguments are required.\n");
return -1;
}
file_path = argv[1];
a = atof(argv[2]);
b = atof(argv[3]);
if( a == 0.0 ) {
printf("Error: bad float arg\n");
return -1;
}
if( b == 0.0 ) {
printf("Error: bad float arg\n");
return -1;
}
FILE* fp = fopen( file_path, "r");
if( fp == NULL ){
printf( "Error: bad file; %s\n", file_path);
return -1;
}
while( fgets( filedata, 200, fp ) ){
printf("%s", filedata);
}
fclose(fp);
}
At the very bottom I have began to read a file. What I am trying to do is find files that contain the characters "#A#" and "#B#" and then print an error message when files containing these characters are not present.
Unfortunately, a simple if statement will not work in this scenario as I am not checking for equality but rather whether or not something is present.
If anybody could tell me about any C functions that are able to read and check the contents of a file, along with a few more specifics, then I would highly appreciate it!
After taking each line (into 'filedata') simply use the strstr function to check if it contains that substring "#A#" etc.
if strstr finds the substring it will return a pointer to it, otherwise it will return a NULL pointer.
So you should write something like this:
if ( strstr(filedata, "#A#") == NULL )
printf("Error\n");
but since you are looking at the entire file for this substring, you need to check all the lines before you conclude that there is an error.
I am trying to count the number of lines and characters whatever they may be in a file that I specify from argv. But I get a segmentation fault when I hit the while loop for some reason. The program runs fine without the while loop, though it only goes through once.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
if(argc != 2) {
return 0;
}
FILE *fp;
char c;
int lines = 0;
int chs = 0;
fp = fopen(argv[1], "r");
//Segmentation Fault happens here on the while loop
while((c = fgetc(fp)) != EOF) {
if(c == '\n') {
lines += 1;
}
else {
chs += 1;
}
}
printf("Charaters: %d\n", chs);
printf("lines: %d\n", lines);
if(fp){
fclose(fp);
}
return 0;
}
Your code needs to be follow Idiomatic C more closely.
You should validate fopen immediately, instead of after you've already attempted to use fp.
fgetc returns int, not char. This is because it needs to return side-channel information about the status of the stream (i.e. EOF), this information cannot be represented by char, but you can safely cast the int value to char if the value is not EOF.
Your code treats \r as a regular character when it is commonplace for \r\n to represent a line-break (not just a solitary \n), you might want to consider how you handle different character classes.
Your program does not handle non-trivial encodings (i.e. it will only correctly handle files in your system's native encoding, presumably ASCII). You should use a Unicode library to correctly read individual characters from a file: for example your program will treat a surrogate-pair in UTF-8 as two characters instead of 1, and would incorrectly count UTF-16 files.
Better:
FILE* fp = fopen( argv[1], "r" );
if( !fp ) {
printf( "Could not open file \"%s\" for reading.\r\n", argv[1] );
return 1;
}
int lines = 0;
int chars = 0;
int nc;
while( ( nc = fgetc( fp ) ) != EOF ) {
char c = (char)nc;
if ( c == '\n' ) lines++;
else if( c != '\r' ) chars++;
}
printf( "Characters: %d\r\nLines: %d\r\n", chars, lines );
fclose( fp );
return 0;
So I know that's a long title, but I'll try break it down a bit.
I'm trying to create a C program, that will read in an undetermined number of integers from .txt file (under the assumption that the file ONLY contains integers, and each integer is separated by a new line), before then converting each one to binary form, and then exporting it to the screen.
I'm trying to create the program step-by-step, and so far I have managed to create a program which converts to binary, but only from a single user inputted integer (see the code below).
#include<stdio.h>
int main(){
long int integerInput,quotient;
int binaryNumber[100],i=1,j;
printf("Enter any integer: ");
scanf("%ld",&integerInput);
quotient = integerInput;
while(quotient!=0){
binaryNumber[i++]= quotient % 2;
quotient = quotient / 2;
}
printf("Equivalent binary value of integer %d: ",integerInput);
for(j = i -1 ;j> 0;j--)
printf("%d",binaryNumber[j]);
return 0;
}
I'm really not sure how to effectively read in the numbers and convert them one by one. I have tried a for loop like below, on a test file which contains 10 different integers (I have declared this file and opened it using the neccessary File I/O).
I tried editing the above code using a for loop, but this doesn't seem to help - it just generates random sequences.
for(k=0;k<10;k++)
{
fscanf(test, "%d", &decimalNumber);
.... // rest of above code is inserted here, minus the scanf and prompts for user to enter a number
return 0;
}
Any help is deeply appreciated!
some recommendations:
use int64_t from #include<stdint.h> instead of long int.
check for errors, is scanf succeeded or not:
if (scanf("%ld", &integerInput) != 1){
printf("incorrect input.\n");
return 1; // error
}
you can use OS-pipe/Redirecting standard input or files: https://en.wikipedia.org/wiki/Redirection_(computing)
so you can use scanf for both user input(stdin) and file input(os pipe).
this simpilies you code.
so the rest is simple:
use loop then inside loop: read input with scanf then convert to binary then printf:
you can use itoa from #include<stdlib.h> to Converts an integer to a string:
int32_t n = 1234567890;
char buf[65];
itoa(n, buf, 2);
printf("%s\n", buf); // 1001001100101100000001011010010
and put together,
working sample code:
#include<stdio.h>
#include<stdint.h>
#include<stdlib.h>
int main(){
int32_t n = 1234567890;
char buf[65];
while (1){
if (scanf("%ld", &n) != 1){
//printf("incorrect input\n"); // or EOF
return 1; // error or EOF
}
itoa(n, buf, 2);
printf("%s\n", buf); // 1001001100101100000001011010010
}
return 0;
}
And call it like: file1 < file2.txt
or you may use fscanf if you want to.
i hope this helps.
A simple way to loop through your input file would be:
while( fscanf( fp, "%ld", &inputInteger ) == 1 )
{
// convert and display inputInteger
}
where fp is your input stream. *scanf returns the number of successful conversions and assignments; since we are only reading a single item, we expect a return value of 1 on success. This will loop until EOF or fscanf sees a non-whitespace, non-decimal-digit character.
You can have your program read from either a file or standard input with an optional command line parameter:
int main( int argc, char **argv )
{
FILE *fp = stdin; // default to standard input
if ( argc > 1 )
{
if ( !(fp = fopen( argv[1], "r" )) )
{
fprintf( stderr, "Could not open %s\n", argv[1] );
return EXIT_FAILURE;
}
}
while ( fscanf( fp, "%ld", &inputInteger ) == 1 )
{
// convert and display integer
}
if ( fp != stdin )
fclose( fp );
}
how to read a negative number from a file using fgetc?
fgetc only reads one character at a time. If you are trying to read in a negative number from a file -- or any number -- use fscanf.
#include <stdio.h>
main()
{
int v;
fscanf (stdin, "%d", &v);
printf ("v = %d\n", v);
}
If the "structures" in the title implies binary, then you likely want to use fread(), but if you really are chasing the question of what the layout of the integer stored in a binary file is, you can use fgetc().
This code shows how to use a union to map a series of read bytes back into an integer.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
union Integer
{
int intPart_;
char charPart_[4];
};
int main(int argc, char* argv[])
{
FILE* pFile = fopen("integerFile.dat", "w");
int intWritten = -257;
size_t bytesWritten = fwrite(&intWritten, 1, sizeof(int), pFile);
assert(bytesWritten == sizeof(int));
fclose(pFile);
pFile = fopen("integerFile.dat", "r");
int intRead = 0;
size_t bytesRead = fread(&intRead, 1, sizeof(int), pFile);
assert(bytesRead == sizeof(int));
printf("%d\n", intRead);
fclose(pFile);
pFile = fopen("integerFile.dat", "r");
Integer intToRead;
for(int i = 0;
i != sizeof(int);
++i)
{
int byteRead = fgetc(pFile);
intToRead.charPart_[i] = byteRead;
printf("%d\n", byteRead );
}
printf("%d\n", intToRead.intPart_);
fclose(pFile);
return 0;
}
How's the number encoded?
If it's ASCII, remember it takes more than one character. You can write a loop for it, but you might find fscanf more help.
If it's binary data, remember fgetc is only going to read 8 bits anyway -- again, you need to think about other functions to do it efficiently.
The point here really is that unless you're doing it just to prove you can, fgetc is probably the wrong answer. Maybe fgets?
fgetc() interprets the character as an "unsigned char", but casts it to an int (but returns EOF, which is -1, on end of file).
If your source file contains some representation of signed values, then you need to decode that.
'0' has the ascii value 0x30、'1' is 0x31... and so far...
Assuming you have only one number in your file:
FILE * pFile;
int c, n = 0;
bool negative;
pFile=fopen ("myfile.txt","r");
if (pFile==NULL){
perror("Error opening file");
}else{
c = fgetc (pFile);
negative = (c == '-');
do {
c = fgetc (pFile);
if (c>=0x30 && c<=0x39) {
n = n*10 + (c-0x30);
}
} while (c != EOF);
fclose (pFile);
}
if(negative==true) n=n*-1;
printf ("Your number: %d\n",n);
I am with Charlie on the point that there are far better ways to do this than with what would need to be multiple calls to fgetc but if you insist on using that function you would need to run through a loop that evaluates each char. It also does depend on how the data is encoded. If it is ascii (as using a func that returns char would imply) you would check to see if the first char is "-" and then convert each subsequent char to int with atoi(const char*) one at a time, and multiplying your result value by ten each iteration before adding the new value to it. A better way would be to read several chars (using fgets or something) and then convert the char* with atoi(const char*). Maybe if you described more clearly what you were trying to do a better answer could be provided. Beware that using fscanf will fail if your data is not formatted exactly as you specify. But fscanf is really your answer for this problem it seems.
Without over/underflow-check you can use fscanf WITH return-value check:
#include <stdio.h>
int main()
{
int v;
if( 1==fscanf(yourfilepointer, "%d", &v) )
printf ("v = %d\n", v);
else
fputs("error on reading v",stderr);
return 0;
}