Program that prints specific characters from a line in a file - c

This is a programming problem i stumbled upon. It requires some specific stuff to be done and that is the reason that i copy files etc. The problem is that it requires that i print out the last character from onoma, the first character from epithetoand the product of the four digits of afm. The thing is that it must be done by reading the file. My code is the following:
#include <stdio.h>
main()
{
FILE *fp, *fp2;
char ch;
char onoma[12];
char epitheto[25];
char afm[4];
char adt[8];
fp = fopen("C:\\Users\\kostikas\\Desktop\\New folder\\myfile.txt", "w");
printf("Dose onoma: \n");
scanf("%s", &onoma);
printf("Dose epitheto: \n");
scanf("%s", &epitheto);
printf("Dose afm: \n");
scanf("%s", &afm);
printf("Dose adt: \n");
scanf("%s", &adt);
fprintf(fp, "%s \n%s \n%s \n%s \n", onoma, epitheto, afm, adt);
fclose(fp);
fp = fopen("C:\\Users\\kostikas\\Desktop\\New folder\\myfile.txt", "r");
fp2 = fopen("C:\\Users\\kostikas\\Desktop\\New folder\\myfile2.txt", "w");
while((ch = fgetc(fp)) != EOF)
{
fputc(ch, fp2);
}
fclose(fp);
fclose(fp2);
fp2 = fopen("C:\\Users\\kostikas\\Desktop\\New folder\\myfile2.txt", "r");
}
I have absolutely no idea on how to continue from here. I'm utterly baffled. If my post is against community guidelines please let me know and i will delete it. Your help would be greatly appreciated though. Thank you.

This is a bunch of tasks smashed together, any one of which is a challenge to a beginner. Let's break this into parts.
The problem is that it requires that i
print the last character from onoma
print the first character from eponimo
print the product of the four digits of afm.
We'll focus on those one at a time.
The thing is that it must be done by reading the file.
And leave this for later, it just complicates everything. First get the logic working with hard coded values, then worry about where the input comes from.
print the first character from eponimo
Each character can be accessed with eponimo[n] starting at 0. First character is eponimo[0], then eponimo[1], and so on. Printing the first character is just...
char eponimo[] = "Basset hounds got long ears";
printf("%c\n", eponimo[0]);
We use %c, not %s, because it is a single character, not a string which is a pointer to an array of characters.
print the last character from onoma
The last character would be the length of the string, minus 1 because it starts from 0. You get the length of a string with strlen.
char onoma[] = "Oodles of poodles jump der strudel";
size_t onoma_length = strlen(onoma);
printf("%c\n", onoma[onoma_length-1]);
print the product of the four digits of afm.
This is a little trickier. It requires math, loops, and converting characters to integers.
First, check that afm is long enough, again using strlen.
if( strlen(afm) < 4 ) {
fprintf(stderr, "afm must have at least four digits\n");
exit(1);
}
You can also check if the characters are digits with isdigit.
Then we can loop through the first four characters.
char afm[] = "123456";
for( int i = 0; i < 4; i++ ) {
printf("%c\n", afm[i]);
}
Now we need to turn them into integers. Whole strings are done with atoi (ASCII to Integer), but we want single characters. The thing about characters in C is they're just integers and we can do math on them. 0 is 48, 1 is 49, and so on. We take advantage that all the integers are in a sequence.
char afm[] = "123456";
for( int i = 0; i < 4; i++ ) {
// '0' - '0' is 0.
int digit = afm[i] - '0';
printf("%d\n", digit);
}
Note that I've switched to %d for printing an integer (a "digit").
Now we multiply them.
char afm[] = "123456";
int product = 1; // start with 1, not 0, else it will always be 0
for( int i = 0; i < 4; i++ ) {
// '0' - '0' is 0.
int digit = afm[i] - '0';
product *= digit; // same as product = (product * digit)
}
printf("%d\n", product);
Now that you know how to do it with fixed strings, you can substitute what you've read from the file. First, open it for reading and check that it worked. This check will save you a lot of misery.
char filename[] = "C:\\Users\\kostikas\\Desktop\\New folder\\myfile.txt";
fp = fopen(filename, "r"); // open for reading
if( fp == NULL ) {
perror("Could not open input file");
}
Now allocate memory and read lines. scanf reads from "standard input", roughly what you tyope into the program. fscanf reads from a filehandle.
// Allocate space for 10 characters.
// Read only 9 because strings need an extra null character to indicate the end.
char onoma[10];
fscanf(fp, "%9s", onoma);
char eponimo[10];
fscanf(fp, "%9s", eponimo);
char afm[10];
fscanf(fp, "%9s", afm);
// We're done reading, close the file.
fclose(fp);
However, scanf and fscanf have a lot of surprising behaviors. And we need to preallocate our best guess of how much we're going to read and be careful not to read in more than we've allocated.
If at all possible, use getline instead. Most compilers support it. It will allocate memory for you. It doesn't have the caveats of fscanf, but it also doesn't strip the newline off the end like fscanf does.
size_t size = 0;
char *onoma = NULL;
getline(&onoma, &size, fp);
Writing is easier. Open the file for writing, you know how to do that, and use fprintf instead of printf, like fscanf instead of scanf.
fprintf(fp, "%c\n", eponimo[0]);
That should get you going. This exercise is throwing multiple problems at a beginner. Break them up into parts and tackle them one at a time.

Related

Finding sum of ints in a string

I need to output the sum of the numbers that are inside of a sentence.
For example :
input: abc3x casa2 y34zq
output : 3+2+3+4 = 12
I need to read all the sentences include the space to do this, but my loop with getchar doesn't work. Can help me to find the problem?
int main() {
int i = 0;
int somma = 0;
char s[MAX];
printf("inserisci la stringa : ");
scanf("%s",s);
while((s[i] = getchar()) != '\n'){
i++;
if(s[i]>'0' && s[i]<'9'){
somma+= (int)s[i]-(int)'0';
}
}
printf("la somma è = %d", somma);
}
I don’t have to use getchar. I would prefer to use fgets because I know that fgets can read the entire line including the space.
Since you are ok with using fgets() you can read the entire line and then use isdigit() to find the numbers.
FILE *fp;
fp = fopen("file.txt" , "r");
if(fp == NULL) {
perror("Error opening file");
return(-1);
}
char line[MAX];
if( fgets(line, MAX, fp) == NULL ) { // Read entire line
perror("Error reading file");
return -1;
}
int sum = 0;
int len = strlen(line);
for (int i = 0; i < len; i++) {
if (isdigit( (unsigned char)line[i] )) { // cast handles negative values of line[i]
sum += line[i] - '0'; // Add integer value to sum
}
}
The basic idea is the same, only this loops over a string directly instead of trying to read it with getchar() at each step.
There are two ways to solve your problem.
Get entire string in one go from user
To read entire string, you can use scanf as you are using it. It will store entire string in array (s in your case) and then you can parse this array and peform operations as you are doing. Here limitation would be length of string. You can accept string of the MAX size only as your array is of that much size. If you are okay with this, then your code is correct. All you need to do is remove that getChar() from while.
Read one character at a time.
Alternatively, you can read one character at a time from user and immediately perform operations on that character. In that case, you don't need to declare array. One character variable is sufficient and you can go on accepting data from user. In this case, discard the scanf() and in your while(), accept getChar() output in one character and perform your operation.
P.S. There's one small bug in your while() which will give you incorrect result in few cases.

C - reading ints and chars into arrays from a file

I have a .txt file with values written in this format: LetterNumber, LetterNumber, LetterNumber etc (example: A1, C8, R43, A298, B4). I want to read the letters and the numbers into two separate arrays (example: array1 would be A C R A B; array2 would be 1 8 43 298 4). How can I make it happen?
At the moment I only figured out how to read all the values, both numbers and letters and the commas and everything, into one array of chars:
FILE *myfile;
myfile = fopen("input1.txt", "r");
char input[677]; //I know there are 676 characters in my .txt file
int i;
if (myfile == NULL) {
printf("Error Reading File\n");
exit (0);
}
for (i=0; i<677; i++) {
fscanf(myfile, "%c", &input[i]);
}
fclose(myfile);
But ideally I want two arrays: one containing only letters and one containing only numbers. Is it even possible?
I would appreciate any kind of help, even just a hint. Thank you!
Define another array for integers,
int inputD[677];
Then in for loop read one char, one integer and one space char at a time.
fscanf(myfile, " %c%d %*[,] ", &input[i], &inputD[i]);
I would actually define a struct to keep letter and number together; the data format strongly suggests that they have a close relation. Here is a program that exemplifies the idea.
The scanf format is somewhat tricky to get right (meaning as simple as possible, but no simpler). RoadRunner, for example, forgot to skip whitespace preceding the letter in his answer.
It helps that we have (I assume) only single letters. It is helpful to remember that all standard formats except %c skip whitespace. (Both parts of that sentence should be remembered.)
#include<stdio.h>
#define ARRLEN 10000
// Keep pairs of data together in one struct.
struct CharIntPair
{
char letter;
int number;
};
// test data. various space configurations
// char *data = " A1, B22 , C333,D4,E5 ,F6, Z12345";
void printParsedPairs(struct CharIntPair pairs[], int count)
{
printf("%d pairs:\n", count);
for(int i = 0; i<count; i++)
{
printf("Pair %6d. Letter: %-2c, number: %11d\n", i, pairs[i].letter, pairs[i].number);
}
}
int main()
{
setbuf(stdout, NULL);
setbuf(stdin, NULL);
// For the parsing results
struct CharIntPair pairs[ARRLEN];
//char dummy [80];
int parsedPairCount = 0;
for(parsedPairCount=0; parsedPairCount<ARRLEN; parsedPairCount++)
{
// The format explained>
// -- " ": skips any optional whitespace
// -- "%c": reads the next single character
// -- "%d": expects and reads a number after optional whitespace
// (the %d format, like all standard formats except %c,
// skips whitespace).
// -- " ": reads and discards optional whitespace
// -- ",": expects, reads and discards a comma.
// The position after this scanf returns with 2 will be
// before optional whitespace and the next letter-number pair.
int numRead
= scanf(" %c%d ,",
&pairs[parsedPairCount].letter,
&pairs[parsedPairCount].number);
//printf("scanf returned %d\n", numRead);
//printf("dummy was ->%s<-\n", dummy);
if(numRead < 0) // IO error or, more likely, EOF. Inspect errno to tell.
{
printf("scanf returned %d\n", numRead);
break;
}
else if(numRead == 0)
{
printf("scanf returned %d\n", numRead);
printf("Data format problem: No character? How weird is that...\n");
break;
}
else if(numRead == 1)
{
printf("scanf returned %d\n", numRead);
printf("Data format problem: No number after first non-whitespace character ->%c<- (ASCII %d).\n",
pairs[parsedPairCount].letter, (int)pairs[parsedPairCount].letter);
break;
}
// It's 2; we have parsed a pair.
else
{
printf("Parsed pair %6d. Letter: %-2c, number: %11d\n", parsedPairCount,
pairs[parsedPairCount].letter, pairs[parsedPairCount].number);
}
}
printf("parsed pair count: %d\n", parsedPairCount);
printParsedPairs(pairs, parsedPairCount);
}
I was struggling a bit with my cygwin environment with bash and mintty on a Windows 8. The %c would sometimes encounter a newline (ASCII 10) which should be eaten by the preceding whitespace-eating space, derailing the parsing. (More robust parsing would, after an error, try to read char by char until the next comma is encountered, and try to recover from there.)
This happened when I typed Ctr-D (or, I think, also Ctr-Z in a console window) in an attempt to signal EOF; the following enter key stroke would cause a newline to "reach" the %c. Of course text I/O in a POSIX emulation on a Windows system is tricky; I must assume that somewhere between translating CR-NL sequences back and forth this bug slips in. On a linux system via ssh/putty it works as expected.
You basically just have to create one char array and one int array, then use fscanf to read the values from the file stream.
For simplicity, using a while loop in this case makes the job easier, as you can read the 2 values returned from fscanf until EOF.
Something like this is the right idea:
#include <stdio.h>
#include <stdlib.h>
// Wasn't really sure what the buffer size should be, it's up to you.
#define MAXSIZE 677
int
main(void) {
FILE *myFile;
char letters[MAXSIZE];
int numbers[MAXSIZE], count = 0, i;
myFile = fopen("input1.txt", "r");
if (myFile == NULL) {
fprintf(stderr, "%s\n", "Error reading file\n");
exit(EXIT_FAILURE);
}
while (fscanf(myFile, " %c%d ,", &letters[count], &numbers[count]) == 2) {
count++;
}
for (i = 0; i < count; i++) {
printf("%c%d ", letters[i], numbers[i]);
}
printf("\n");
fclose(myFile);
return 0;
}

errors parsing int from text file c

Heres' my code so far, basically I am reading in a text file, and trying to save the each line by line input to a character array. The text file is read properly and saved to a character array which I then traverse through, and attempt to save the digits to an int.
*This isn't the entire code piece, as it's an assignment that I'm working on. The current code provided is simply for debugging purposes.
//takes input of file, saves it to array
char word[20];
scanf("%s", word);
//File to open
char line[10];
char number[10];
FILE *file;
file = fopen(word, "r");
if (file) {
while (fgets(line, sizeof(line), file)) {
printf("%s", line);
int i,j=0;
int parsedInt;
for(i=2; i<sizeof(line) && !isspace(line[i]); i++)
{
number[j] = line[i];
j++;
}
sscanf(number, "%d", &parsedInt);
printf("PARSED INT %d \n\n", parsedInt);
parsedInt = 0;
Here's a sample input file, I have handled the i and d, which works fine.
i 10
i 12
d 10
i 3
and heres sample output with those numbers
i 10
PARSED INT 10
i 12
PARSED INT 12
d 10
PARSED INT 10
i 3
PARSED INT 32
Can someone explain why the last input gives a 32 instead of a 3 while the others are properly done?
Since we're not seeing everything, I'm going to take an educated guess that you're not clearing the number array before putting in values, so scanf() is going past your actual input. Either put a '\0' after your for loop or use memset() or similar to clear the array before use. So like:
memset(number, 0, sizeof(number));
for(i=2; i<sizeof(line) && !isspace(line[i]); i++) {
number[j] = line[i];
j++;
}
This assumes that '\0' == 0 (which is a damn safe assumption IME).

C How to ignore empty lines in user input?

here is my current code:
int num = 0;
char c = '#';
scanf("%d",&num);
do{
for (int i=0;i<num;i++){
printf("%c",c);
}
printf("\n");
}
while (scanf("%d", &num) == 1);
How would I have it so that if the user doesn't enter anything, that the program won't spit out a newline?
Any help is appreciated, thank you!
This code should work for what you want to do :
#include <stdio.h>
int main()
{
int num = 0;
char c = '#';
char readLine[50];
while ((fgets(readLine, sizeof readLine, stdin) != NULL) && sscanf(readLine, "%d", &num) == 1)
{
for (int i=0;i<num;i++){
printf("%c",c);
}
printf("\n");
fflush(stdout);
}
return 0;
}
The behaviour of this code is the following : fgets will read anything you enter in the standard stream (stdin), and put it in the readLine array. The program will then try to read the number which is in your readLine variable and put it in your num variable with the sscanf function. If a number is read, the program will execute the behaviour you did present in your question (writing a # character "num" times), and go back to the beginning of the loop. If anything else than a number has been read, the loop is stopped.
In general, avoid scanf. It's very easy to leave yourself with unprocessed cruft on the input stream. Instead, read the whole line and then use sscanf (or something else) to process it. This guarantees that you won't get stuck with a partially read line, those are hard to debug.
I prefer getline to fgets to read lines. fgets requires you to guess how long the input might be, and input might get truncated. getline will allocate the memory to read the line for you avoiding buffer overflow or truncation problems.
NOTE: getline is it's not a C standard function, but a POSIX one and fairly recent (2008), though it was a GNU extension well before that. Some older compilers may not have it.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char c = '#';
char *line = NULL;
size_t linelen = 0;
/* First read the whole line */
while( getline(&line, &linelen, stdin) > 0 ) {
/* Then figure out what's in it */
long num = 0;
if( sscanf(line, "%ld", &num) > 0 ) {
for( int i = 0; i < num; i++ ) {
printf("%c", c);
}
printf("\n");
}
}
free(line);
return 0;
}
if( sscanf(line, "%ld", &num) > 0 ) { will ignore any line that does not match any part of the pattern, such as a blank line or a line full of words, by checking how many things matched. Yet it will still handle 0 as a valid input.
$ ./test
foo
bar
foo123
12
############
1
#
0
2
##
I also moved num inside the loop to guarantee it's reinitialized each iteration, and on the general principle of putting your variables in minimum scopes to avoid interference. And I upgraded it to a long int better able to handle the unpredictably large numbers users might type in.
Here is how I have done input parsing over the years using the fgets() and sscanf() functions. I don't write c++ much, and if I can I keep code within old style ansi C then I do.
The fgets and sscanf functions from the stdio.h library are universal and are always available on any platform.
For a character array used to read in anything, I generally set LINE_SIZE to 256 or 512 even if I know typically the line to be read is 80 characters or less. With any computer today having over 1GB of RAM, not worth worrying about allocating an extra 500 or so bytes. Obviously, if you have no idea how long the input line is then you either have to:
guess at what LINE_SIZE should be set to and not worry about it
or verify a newline character is present in line[] prior to a null character after calling fgets().
# include <stdio.h>
# define LINE_SIZE 256
int main ( int argc, char *argv[] )
{
FILE *fp;
char line[LINE_SIZE];
int nn;
int value;
fp = fopen( "somefile", "r" );
fgets( line, LINE_SIZE, fp );
/*
this way to read from standard input (i.e. the keyboard)
using fgets with stdin prevents compiler warning when using
deprecated gets function
fgets( line, LINE_SIZE, stdin );
*/
if ( line[0] != '\n' )
{
/* definitely not a blank line */
nn = sscanf( line, "%d", &num );
if ( nn == 1 )
{
/* some number placed into num variable that met the
%d conversion for the sscanf function
*/
}
}
return 0;

While loop through text file stops unexpectedly

I am trying to loop through a text file that contains random content. It's current contents are:
"13 -35 57 - 23723724
12taste-34the+56rain-bow845"
My program should only get the numbers from the file (-35 as a negative number, but not - 23723724 due to the space in between) and no letters or other characters unrelated to the integer.
Currently my code has a while loop that runs through the file and fetches all the decimal values. For some unknown reason however, it stops after 57 (total result is: "13-3557" and then it stops).
I have attempted to iterate over every character seperately but that brought along it's own set of problems and this method at least returns whole numbers.
Here is my code:
int *getIntegers(char *filename, int *pn) {
// Create a dynamic array
int len = 100;
int *numbers = malloc(sizeof(int) * len);
// Source file
FILE *file;
file = fopen(filename, "r");
int i = 0, number = 0;
while(fscanf(file, "%d", &number) > 0) {
numbers[i++] = number;
printf("%d", number);
}
return numbers;
}
EDIT:
I have changed my code and it now retrieves all the numbers, but no spaces.
// Create a dynamic array
int len = 100;
int *numbers = malloc(sizeof(int) * len);
// Source file
FILE *file;
file = fopen(filename, "r");
int i = 0, number = 0;
while(!feof(file)) {
if(fscanf(file, "%d ", &number) > 0) {
numbers[i++] = number;
} else {
clearerr(file);
fgetc(file);
}
}
fclose(file);
return numbers;
When the input stream encounters - and it expects to see an integer, it does not read anything. It stops there.
If you want to continue reading the rest of the numbers, you'll need some code that reads the next characters, discards it, and continues on.
while(!foeof(file) )
{
if ( fscanf(file, "%d", &number) > 0) {
numbers[i++] = number;
printf("%d", number);
else {
clearerr(file); // Clear the error state.
fgetc(file); // Read the next character and discard it.
}
}
Update
To add a space between the numbers in the output, use:
printf("%d ", number);
fscanf doesn't keep looking at its input until it finds something matching its patters. In this case, it encounters the lone -, and unable to parse it into an integer, returns zero. This breaks your loop. You will need to use EOF to break your loop instead.
It's because fscanf sees the lonely '-' and as that's not a valid number it cant parse it and returns 0 which causes your loop to end.
I suggest you use fgets to read the whole line, and then use strtok to separate on space, and strtol to convert the tokenized strings to numbers.

Resources