We have an assignment which is to take characters from a file, shift it a given value to the right(it'll make sense in the code) and then store that new value in a new file, but I seem to be running into a segmentation fault, which as far as I know means I'm trying to access memory outside of the memory I have been allocated? I'm very new to C and I managed to debug this code up until this point and I honestly don't know where to go. I don't even quite understand what the issue is.
#include<stdio.h>
//Get Shift amount
//Get ifilename
//Get ofilename
//open them
//Get characters one at a time from input
//Process and shift by shift amount
int main()
{
int i;//loop value
char a[62]="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";//Variable with every value
int sa = 0;//Store Shift value
char ofile[30];//contain the name of output file
char ifile[30];//contain name of input file
char value;//Value to keep the current value in
printf("How far in ascii values would you like to shift?\n");
scanf("%i", sa);//Get shift
printf("What is the name of your input file located in this directory?");
scanf("%s", ifile);//get input name
printf("What would you like to name your new file?\n Do note that it will overwrite the current file named this!");
scanf("%s", ofile);//Get output name
FILE *oIfile = fopen(ifile, "r"), *oOfile = fopen(ofile, "w");
while(value = fscanf(oIfile, "%c", value) != EOF)//Check to ensure that you never reach the end of the file
{
for(i=0; i<62; i++)//loop through the list of all characters
{
if(value == a[i])//check to see if the value from the input file matches with which letter
{
value = a[i+sa] % 62;//incrase the value by the shift amount, check if its longer than 62, add remainder
break;//break the for loop so we can restart the while loop with the next letter
}
}
fprintf(oOfile, "%c");//print the new value to the output file
}
fclose(oIfile);//close input file
fclose(oOfile);//close output file
}
is this issue due to my approach to scanf?
Apart from passing the address to scanf (scanf("%i",&sa) which you would have to do (Also it would be correct to check the return value of it) - you need to correct a few things:-
It should be (value = fscanf(oIfile, "%c", value)) != EOF. != has higher precedence than = so this is needed to get the correct result.
Also a[(i+sa)%62]=... is the right way to do things. Because otherwise it will access array index out of bound for certain values of sa leading to undefined behavior.
fprintf(stream,"%c",charvariable) this would be the use for fprintf.
The value is over written with what is being returned by the value that fscanf returns. You should use other temporary variable or even better simply do like this while(fscanf(oIfile, "%c", value)!=EOF). But to have more checks you need to do somehting like
int c;
while((c=fscanf(oIfile, "%c", value))!=EOF)
You got segmentation fault here by passing the value of sa instead of its address in scanf.
scanf take an address as a parameter. Try this;
scanf("%i", &sa);//Get shift
Related
I'd like some assistance with understand how inputting data in a program of C works. So far I'm used the java syntax having the convenient try{}catch(){}; clause but I don't see it anywhere on C (or I haven't found it?).
Assuming I have the following array;
float f_array[10];
Normally for me to input data I'd either use a scanf(...); or a file which I can read input from, but for the shake of simplicity let's assume I use scanf(...);
And I have the following;
int i;
for(i = 0; i<10; i++){
scanf("%f", &f_array[i]);
}
Now , my question is how to restrain the user from putting in the input a character or a string or the wrong data type for that matter? Also , should I always try to initialize the array before actually putting values in it?
Note that scanf() returns number of elements successfully read, you can check it:
int success = scanf(...);
if (!success) {
scanf("%*[^\n]%*c"):
// OR while(getchar() != '\n');
}
There is, however, a complex solution. You don't use scanf(), but write a custom input method that processes keystrokes and filters out invalid characters, possibly using getch() (Windows/nCurses). Here's a minimized Windows version:
void readFloat(float* in){
int ch, ind = 0;
char buf[100];
while (1){
ch = getch();
if (ch >= '0' && ch <= '9' || ch == '.') {
buf[ind++] = (char)ch;
putchar(ch);
}
else if (ch == 8) /* Backspace */ {
printf("\b \b");
ind --;
}
}
buf[ind] = '\0';
float ret;
sscanf(buf, "%f", &ret);
return ret;
}
So a possible result of the code:
User input (key presses): 123aaa.bbb456
Program filter (displayed on screen): 123.456
Return value: (float)123.456
Now , my question is how to restrain the user from putting in the input a character or a string or the wrong data type for that matter?
Without dedicated hardware support (say, using a keyboard that does not have letter keys, or some device that gives the user an electric shock to discourage them from hitting the 'A' key) there is no way to restrain a user from entering unwanted data.
Instead, you need to write your code with the ASSUMPTION that the user will enter invalid or poorly formed data, and cope with that. It is true that your code is simpler if you can assume an obedient and tractable user who only gives correct input, but the real world isn't like that.
scanf() - reading and interpreting data directly from stdin doesn't actually work well with such an assumption. The return value from scanf() can give you an indication a problem after the fact (e.g. the return value is number of fields successfully input, or EOF). However, when a problem occurs, scanf() handles it in a way you cannot control. Let's say you code has a
scanf("%f", &f_array[i]);
and the user hits the 'X' followed by the Enter key. scanf() will recognise the 'X' character is waiting to be read, and return immediately. The value it returns will not be 1 (which would indicate success). Even worse, the 'X' will be left to be read by a subsequent call of scanf() and the same will happen again (unless a different format is specified). Which means, if you call scanf() in a loop this way, the same will happen over and over again.
Some folks will tell you to simply find a way to read and discard the character 'X'. The problem with that approach is that there are MANY ways for the user to enter bad inputs, and you need to account for all of them. If the user does something you (or your code) doesn't expect, you get problems (e.g. program hanging waiting for the same input repeatedly, input being used as data when it isn't). You're back where you started.
The more robust approach is to simply read a line of input, and do checks before trying to extract a floating point value from it, such as
char buffer[20];
int got_one = 0;
while (!gotone && fgets(buffer, sizeof buffer, stdin) != NULL)
{
if (check_string(buffer))
{
if (sscanf(buffer, "%f", &f_array[i]) == 1)
{
/* yay - we got a floating point value */
got_one = 1;
}
else
{
fprintf(stderr, "Floating point scanning failed. Try again\n");
}
}
else
{
fprintf(stderr, "Bad data discarded. Try again\n");
}
}
Essentially, this provides several hooks so you can check user input in various ways. If you want to, it can be adapted to discard part of a line, and scan useful data from whatever's left.
The key, however, is that the code does not assume the user is well behaved. It only attempts to read a floating point value after a gauntlet of checks, and still copes if the reading fails.
The code can also be adapted to deal with users who enter data that overflows the buffer (e.g. entering 30 floating point characters on a single line). I'll leave that as an exercise.
Also , should I always try to initialize the array before actually putting values in it?
That depends on the needs of your code, but generally speaking I would not bother.
With approaches like I suggest above, you can avoid a circumstance of using the array (or elements of the array) unless valid data has actually been put into it.
All initialising the array will do is obscure cases where the code doing input (reading from the user) has not properly dealt with bad user input.
give the user some feedback on a per input basis.
process each input and allow user to make corrections as you go.
use "atof()" to do the conversion, but it has a couple of quirks:
it tells you there is an error by returning a value of 0.0
it stops processing if/when it finds an invalid char and returns what it has up to that point
eg. 6.35k gives 6.35 -- this usually works out ok;
otherwise you have to check for invalid chars yourself.
try this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main () {
float f_array[10];
int i;
float input_value;
char temp_string[32];
for(i = 0; i<10; i++){
printf("input a floating point number: ");
scanf("%s",&temp_string[0]);
input_value = atof(temp_string);
while(input_value == 0.0) {
printf("%s is not a valid floating point number\n");
printf("example is 5.6 or 1e32 or 17\n");
printf("try again - input a floating point number: ");
scanf("%s",&temp_string[0]);
input_value = atof(temp_string);
}
f_array[i] = input_value;
printf("String value = %s, Float value = %f\n", temp_string, input_value);
}
/* use the data */
for(i = 0; i<10; i++){
printf("%f\n",f_array[i]);
/* do something */
}
}
Im still considered a beginner in c and i started learning about files. i already built a blank file. Every time i compile this program, the file is still blank. Need help!!
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE * x;
char name[25];
printf("enter your name: ");
scanf("%s", &name);
x = fopen("x1.txt", "w");
if(x = NULL)
{
printf("Unable to open the file");
}
else
{
fprintf(x, "%s\n", name);
printf("date has been entered successfully to the file");
fclose(x);
}
return 0;
}
Thank you
A file existed, and contained my name, after making the following changes and rebuilding/running the program:
(see comments in line for reasons)
Change:
if(x = NULL)//assignment - as is, this statement will always evaluate
//to false, as x is assigned to NULL.
To:
if(x == NULL)// comparison - this will test whether x is equal to NULL without changing x.
Change: (this was key to your file not being populated)
scanf("%s", &name);//the 'address of' operator: '&' is not needed here.
//The symbol 'name' is an array of char, and is
//located at the address of the first element of the array.
To:
scanf("%s", name);//with '&' removed.
Or better:
scanf("%24s", name);//'24' will prevent buffer overflows
//and guarantee room for NULL termination.
Yet one more method to address the comment about not using scanf at all...:
char buffer[25];//create an additional buffer
...
memset(name, 0, 25);//useful in loops (when used) to ensure clean buffers
memset(buffer, 0, 25);
fgets(buffer, 24, stdin);//replace scanf with fgets...
sscanf(buffer, "%24s", name);//..., then analyze input using sscanf
//and its expansive list of format specifiers
//to handle a wide variety of user input.
//In this example, '24' is used to guard
//against buffer overflow.
Regarding the last method, here is a page detailing the versatility of handling user input strings using sscanf.
Hi guys how to read entire digits from file? I mean my input file is 100-4/2 and i wrote this code while(fscanf(in,"%s",s)!=EOF) but it read like this 1 0 0. I want read like 100. How to solve this?
It's probably because you are using one-byte character(ANSI) set while the file is written with two-byte characters(Unicode). If you have created the file with the same program that is reading it it's going to read it right, but if not, you can open the file you are reading in notepad, then click save as, and there you can choose ANSI or Unicode.
You can read the whole line at once using getline() or similar method (also you can read as you are doing if there is only one line, then when EOF is true, whole line is read). Then you can parse the line to extract numbers and operators.
Use "%d" for integers
int value;
if (scanf("%d", &value) != 1) /* error */;
printf("Value read is %d.\n", value);
The below is simple program is self explanatory, which reads a file character by character, for each iteration stores this character into a temporary variable temp. and when the value in temp is a numerical character it simply copies this value in array named s.
int main()
{
char s[10]="\0";//initialzing array to NULL's and assuming array size to be 10
int i=0,temp=0;
FILE *fp=fopen("t.txt","r"); //when file has 100-4/2
if(fp==NULL)
{
printf("\nError opening file.");
return 1;
}
while( (temp=fgetc(fp))!=EOF && i<10 ) //i<10 to not exceed array size..
{
if(temp>='0' && temp<='9')//if value in temp is a number (simple logic...)
{
s[i]=temp;
i++;
}
}
printf("%s",s);//outputs 10042
return 0;
}
I am reading data from a file, retrieving how many columns and rows I have ( data file ), everything of so far. Now I am trying to read the values one by one and store the values in to a 2D array (double). I get the values as char using getc but when I try to use atoi or atof to convert the values from char to double i get strange values.
double ther[j][number];
char c;
int tim=0,nther=0;
FILE *fp3 = fopen("data.txt", "r");
c = getc(fp3) ;
while (c!= EOF)
{
ther[tim][nther]=atoi(&c);
printf("%lf", ther[tim][nther]);
nther++;
c = getc(fp3);
if(nther==number)
{
tim++;
nther=0;
}
tim=0;
}
fclose(fp3);
any suggestion?… (i keep searching). Sorry well i have a file data.txt and this file has rows an columns of numbers:
1 2 3 4 5
6 7 8 9 10
So i need to store the data into a 2D array: Thanks to the answers i have some ideas like: use an string, then divide all values and stored every one of them. 1st line is string-> array[0][0], array[0][1], etc. Then move to the other row and do the same.
Until now i get some numeric values but none of them are stored at the data.txt.
Firstly, it should be int c;. The getc() function has to be able to return a different value for all possible chars, and also a different value EOF (which signifies end-of-file, or stream error).
If you use char c;, then you must end up with EOF being converted to the value of a legal character, so you can't tell the difference between the two cases. In other words, your code might act like it hit EOF when in fact it just hit that particular character.
Moving on, atoi(&c) is not correct. If you read the documentation for the atoi function -- this is always a good idea when using functions -- you will find that it expects a string as input. However, &c is not a string. It is the address of a single char.
So your options are:
construct a string and pass it to atoi
don't use atoi
You didn't say what you were expecting to happen; but if you want to convert the character you read in of '3' to be the integer 3 then you can write: ther[tim][nther] = c - '0';.
However you should also have some code to handle cases when you read something that was not a number.
If you wanted to read in more than one character at a time (e.g. "31" -> 31) then the approach of using getc is not appropriate - you'll need to switch to using a function that reads multiple characters at once, such as fscanf or fgets.
Finally, you set tim to 0 every single loop iteration, so the tim++ never has any lasting effect, maybe this was an oversight.
You can read a double from a file using fscanf. An example would be:
double d;
fscanf("%f", &d);
fscanf can do much more than that so I'd recommend checking the documentation.
The method you're using gets a single character (as Matt McNabb pointed out - incorrectly). A character is 1 byte and can store the values 0-255. You're reading in text mode since you don't specify a mode with fopen (it is generally considered a good practice to explicitly ask for either binary "rb/wb" or text "rt/wt" mode). This means you read the ASCII value of a single digit.
So let's say the file contains:
7.2, 3.0, 1.0
The first call to getc(fp3) would get the character '7' which would have a value of 55 for ASCII. Obviously this is not going to give you what you're looking for.
Instead you could use:
double d[3];
fscanf("%f, %f, %f" &d[0], &d[1], &d[2]);
Which would get the three float values in the file.
#include <stdio.h>
int main(){
int j = 2;
int number = 5;
double ther[j][number];
double d;
int tim=0,nther=0;
FILE *fp3 = fopen("data.txt", "r");
while (fscanf(fp3, "%lf", &d)==1){
ther[tim][nther]=d;
printf("%g ", ther[tim][nther++]);
if(nther==number){
++tim;
nther=0;
printf("\n");
}
}
{
int r, c;
for(r=0;r<tim;++r){
for(c=0;c<number;++c){
printf("%f ", ther[r][c]);
}
printf("\n");
}
}
return 0;
}
I've been stuck for a while now. The program i'm writing basically changes the false words with the correct ones from the dictionary. However, when i run the program, it gives me no warnings or errors, but it doesn't display anything. Can you please help me?
#include<stdio.h>
#include<ctype.h>
#include<string.h>
int main(void){
char fname[20],word[2500], dictn[50];
int i,j;
float len1, len2;
FILE *inp, *dict, *outp, *fopen();
fpos_t pos1, pos2;
dict= fopen("dictionary.txt", "r");
printf("Enter the path of the file you want to check:\n");
scanf("%s", fname);
inp= fopen(fname, "r");
for(i=0;(fscanf(inp, "%s", word) != EOF); i++){
for(j=0;fscanf(dict, "%s", dictn) != EOF; j++){
fgetpos(inp, &pos1);
fgetpos(dictn, &pos2);
len1=(float)strlen(word);
len2=(float) strlen(dictn);
if(len1<=(0.6*len2)){
fsetpos(dictn, &pos1);
}
if(strncmp(word, dictn, 1)==0){
fsetpos(dictn, &pos1);
}
if(strcmp(word, dictn)==0){
fsetpos(dictn, &pos1);
}
}
printf("%s ", word);
}
fclose(inp);
fclose(dict);
return(0);
}
You can use
sprintf(word, "%s ", dictn);
If your code is working with printf it should work with sprintf, provided you don't overflow "word", including the NULL termination, so you might have to resize "word" if it is smaller than dictn.
First of all, I'm assuming you have created arrays word and dictn with enough size to hold the maximum length string any of your files.
First fault:
In loops you've created, i represents number of strings in input file and j represents number of strings in dictionary. word is your input string variable and dictn is your dictionary string variable. But you want to retrieve and alter word's ith or dictn's jth character. This may cause an error because there can be a case like this:
Suppose there are 10 words at inp file and 100 words at dictn. And in your loops, i have value of 8 and j have value of 88. Corresponding these i and j values, word has string value of, say, apple and dictn has string value of apple also. So this means apple is the 8th word at input file and 88th word at dictionary file. And if one of those if conditions was satisfied, compiler tries to apply a statement like word[i]=dictn[j];. This means word[8] = dictn[88]; for this example. But both of those string have apple as values which consists only 5 characters! And this will cause an error since you've tried to retrieve 88th character of a 5-length string and assign it to the 8th character of a 5-length string. So your code is wrong, it will only work for some cases which will be a rare situation.
Second fault:
I assume you want to read whole dictionary file for every word in input file but you will be able to read it for only first word of input file since you don't reopen it or set position indicator at the beginning of dictionary file after you read whole dictionary.
Third fault:
Your first if statement will never be reached assuming you have created len1 and len2 variables as integers. Because in your if statement, there is a multiplication of a decimal number and an integer which will return 0 as a result and since fscanf() ignores whitespaces, len1 and len2 will be at least 1.
Fourth fault:
Also your else if statement will never be reached because if a string has same value with another, their first character will also be equal to each other and your if statement where you compare their first characters will be also accepted.
Actually, I would write a code as solution but first of all you need to correct things up which are logically wrong because I do not know what you are really try to achieve by your code -just because I commented with full of assumptions-. But I can provide you some guidelines:
Convert your len1 and len2 variables from int to float and cast values which return from strlen() functions to float.
Reopen your dict file for every iteration of outside loop. (And do not forget not to close it).
To change your inp file, you can use a fpos_t type of variable to track your position indicator of your inp file (fgetpos() to get current position and fsetpos() to change position with value of fpos_t variable. You can search them.) and type the word with fprintf() or fputs() to that location to change that string.