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).
Related
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.
EDIT: OK I found the embarrassing mistake. My description array wasn't big enough for that line...
I'm trying to extract related abbreviations and descriptions from a simply formatted text file, but I'm running into a problem on just a single line while every other line works fine.
In the text file I'm reading from, lines 5-7 are:
5. FW Foreign word
6. IN Preposition or subordinating conjunction
7. JJ Adjective
What I'm trying to do with each line is read the abbreviation and store it as a character array and then do the same with the description. For every line except for #6, it works fine.
What I expect is:
print decription[line6] => "Preposition or subordinating conjunction"
But what I get is:
print decription[line6] => "Preposition or subordinating conjunctio"Adjective"
I'm pretty lost as to why it might be doing that. It seems to be reading data from the next line. Or maybe I ended up overwriting the next line into that array.
#include <stdio.h>
int main(){
FILE *fileToRead = fopen("PennTreebank_POS_Tags.txt", "r");
FILE *fileToWrite = fopen("newFile.txt", "w");
int i, j;
i = j = 0;
int nextChar;
char abbreviation[50][5];
char description[50][40];
while( fscanf(fileToRead, "%*s %s ", abbreviation[i]) != EOF ){
description[i][0] = '"';
while( ((nextChar = fgetc(fileToRead)) != '\n') && (nextChar != EOF) ){
description[i][j] = nextChar;
j++;
}
description[i][j] = '"';
description[i][j+1] = '\0';
j=1;
i++;
}
for( i=0; i<36; i++ ){
printf("%s %s\n", abbreviation[i], description[i]);
}
}
The text "Preposition or subordinating conjunction" has a length of 40 chars.
So the array
char description[50][40];
will not be enough size to hold the length 40 plus the 0 terminator.
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.
Im doing a railroad cipher (zigzag cipher) however you may call it, I finally seemed to get my code to work properly and I got it to print the correct output, but unfortunately my teacher calls for the output to be printed 80 columns wide (80 characters per line). Unfortunately, the way my encryption is set up I can not find a way to do this since I set my encryption "rail by rail".
For the assignment we must read in the file, and strip it of all spaces and special characters, and to make all uppercase letters lower-case. Then encrypt the message. My issue is the printing portion in the encrypt function.
since its ran from command line here are the files i used
the first file pointer is for the rails, sample would be: 9
second file pointer is the text, sample i used is:
We shall not flag or fail. We shall go on to the end. We shall fight in France, we
shall fight on the seas and oceans, we shall fight with growing confidence and
growing strength in the air, we shall defend our island, whatever the cost may be, we
shall fight on the beaches, we shall fight on the landing grounds, we shall fight in
the fields and in the streets, we shall fight in the hills. we shall never surrender!
my output is correct according to my teachers output, but unfortunately i get 30% off for not having it 80 characters per line... this is due in a few hours but I can't seem to figure it out. Any help is greatly appreciated.
I would show the output for reference but I don't know how to copy and paste from the command line, and it only runs from there.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
# define MAX 10000
void condense(char* str)
{
int original=0;
int newplace =0;
while (str[original] != '\0')
{
if(isalpha(str[original] ))
{
str[newplace]= tolower(str[original]);
++newplace;
}
++original;
}
str[newplace] = '\0';
}
char * deblank(char *str)
{
char *out = str, *put = str;
for(; *str != '\0'; ++str)
{
if(*str != ' ')
*put++ = *str;
}
*put = '\0';
return out;
}
void encrypt(int rail,char *plain)
{
char railfence[rail][MAX],buf[2];
int i;
int number=0,increment=1;
buf[1]='\0';
for(i=0;i<rail;i++)
railfence[i][0]='\0';
for(i=0;i<strlen(plain);i++)
{
if(number+increment==rail)
increment=-1;
else if(number+increment==-1)
increment=1;
buf[0]=plain[i];
strcat(railfence[number],buf);
number+=increment;
}
for(i=0;i<rail;i++)
printf("%s",railfence[i]);
}
int main(int argc, char *argv[])
{
int rail,mode;
char text[MAX];
FILE* fp1;
FILE* fp2;
fp1 = fopen(argv[1], "r");
fp2 = fopen(argv[2], "r");
int key;
fscanf(fp1, "%d", &key);
printf("key is %d", key);
char c;
int index = 0;
fgets(text, 10000, fp2);
printf("%s \n", text);
// text[index] = '0';
char nospace[MAX];
deblank(text);
printf("text deblanked: %s \n", text);
//printf("%s", deblank(text));
condense(text);
printf("\nthe text condensed is: %s", text);
printf("\n the text encrypted is \n");
encrypt(key,text);
return 0;
}
Simple. Instead of printing each rail as a whole, print each rail character by character, and count. In the example below I assume your instructor's 80 characters per line is 79 characters of ciphertext plus one newline character. I do not know whether you are expected to print a newline at the end of the ciphertext, but if so just add printf("\n"); at the end of encrypt (though you might want to check that there was at least one character of ciphertext before doing so).
void encrypt(int rail,char *plain)
{
char railfence[rail][MAX],buf[2];
int i, col = 0, j, len; // added col, j, and len
int number=0,increment=1;
buf[1]='\0';
for(i=0;i<rail;i++)
railfence[i][0]='\0';
for(i=0;i<strlen(plain);i++)
{
if(number+increment==rail)
increment=-1;
else if(number+increment==-1)
increment=1;
buf[0]=plain[i];
strcat(railfence[number],buf);
number+=increment;
}
for(i=0;i<rail;i++)
{
len = strlen(railfence[i]); // get the length of the rail
for(j=0;j<len;++j) // for each char in the rail
{
printf("%c", railfence[i][j]);
if (++col==79) {
col = 0;
printf("\n");
}
}
}
}
Other than that, I thoroughly recommend using more whitespace in your formatting, as well as checking things like whether the user passes in two arguments or not, whether your files were opened successfully or not, and also remembering to close any files you open.
As result, your program is hard to read, and currently behaves badly if I do not provide both command line arguments or if I give it non-existent files.
I have a txt file that I read each line of it with this function :
the txt file is like this
NOMLOT:300
0001::16:27::47::68:79::3::::43:53::71:81::17:28:31::59:::85
0002:15::32::8::74:79::3::::43:53::71:81::17:28:31::59:::85
my get_line function is here
char *get_line(char *buf, int n, FILE *f, int line)
{
int i;
for (i=0 ;i<line;i++)
{
if(fgets(buf,n,f) == NULL)
return NULL;
buf[strlen(buf) - 1 ] = '\0';
}
return buf;
}
For example if I want to print the first line it will look like :
char input[60];
get_line(input,TAILLE,fichier,ligne);
printf("1st line: \n");
for (i=0;i<60;i++)
{
printf("%c",input[i]);
}
What I want to do , is to read only the 300 and convert that 300 into an INT and save it , so with this value I can loop my program to read the all existing line , starting from the 2nd line .
get_line(input,TAILLE,fichier,ligne);
printf("1st line: \n");
for (i=0;i<60 && input[i];i++){
printf("%c",input[i]);
}
int num;
if(1==sscanf(input, "NOMLOT:%d", &num)){
printf("\n%d\n", num);
}
Ok, first of all, a comment. Your get_line() function is going to be grossly inefficient if you are reading the file sequentially (e.g. read line 1, then read line 2, then read line 3) because you will have to do O(n^2) line reads to read n lines. You should find a way to structure your program so that you read each line at most one time.
As for the actual problem, are you familiar with the C functions strtok and atoi?
Assuming your input buffer contains the line you want (regex "[^:]*:\d+", e.g. "NOMLOT:300"), you can do something like this:
const char * num_pos = strtok(input, ":"); // get the position of the colon
if (! num_pos)
; // colon not found, so handle error
else
{
int num = atoi(num_pos + 1); // convert the string starting one char past the colon to an integer
// do processing now that you have the number...
}