Unable to write shell history to a text file - c

I'm currently writing a shell with basic functions in C, operating through Unix. I'm having difficulty transferring an array of history commands to a text file.
History is stored as a pointer to an array, with a capacity of 20 as not to over-complicate things. I got the basis of the method online so I've tried to tailor it to my needs, however it just feeds a bunch of weird characters to the text file.
Does anyone know why this may be happening?/What I could do to fix it?
I'm also not sure if the for loop is necessary.
Thanks in advance!
char *history[2];
void save(char ** history)
{
FILE *f;
f = fopen("history.txt", "w+");
for(int i = 0; i < 20; i++)
{
fwrite (history, sizeof(history[i]), sizeof(history)/sizeof(history[i]), f);
}
fclose(f);
}

history
is a char **, which is a pointertype.
history[i]
is char*, so still a pointertype
sizeof(history)/sizeof(history[i])
always returns one, since all pointertypes shall have the same size.
So your write statement will print sizeof(< anypointer >) random characters.
Solution
for(int i = 0; i < 20; i++){
fwrite (history[i], sizeof(*history[i]), strlen(history[i]) + 1, f);
}
Notice: This will include the '\0' for each string.
Notice: This will write the internal state into the file, so you should consider to open it in binary-mode or to use:
fputs(history[i], f);
fputc('\n', f); /*or anything similar*/

Related

Saving an integer array to a file in C

I've been trying to write the contents of an integer array to a file in C. I've been using the code below to do so.
int etData [600];
int i;
int size = sizeof(char);
for (i=0; i<600; i++)
{
etData[i] = analog_et(5);
}
FILE *f = fopen("/home/root/Documents/KISS/Default User/Launch Code/data/data", "w");
fwrite(etData, size, sizeof(etData), f);
fclose(f);
analog_et is a function that returns an integer value from a sensor. Whenever I run this code, a mess of ASCII characters is written to the file. I believe this is to blame on the fact that I am passing fwrite an element size sizeof(char) - however, whenever I attempt to pass a value larger than one byte, nothing is written to the file, and fwrite fails to return a non-zero value.
I've looked for a function in stdio that would be better suited to this purpose but can't find one. Any suggestions on how to fix this issue? Thanks!
If you want a textual representation of your data (in that case the file can be opened with a text editor), you cannot user fwrite but you need to use fprintf. Latter does basically is the same thing as printf, but instead of being displayed, the data is written into a text file.
You probably want this:
...
FILE *f = fopen("/home/root/Documents/KISS/Default User/Launch Code/data/data", "w");
for (i=0; i<600; i++)
{
fprintf("%d\n", etData[i]);
}
...

Inserting 400 numbers in a text file

I am trying to write numbers from 1, up to 400 in a text file. I am using the code below, which is running without any errors, but the file is being left empty.
Any help would be appreciated.
#include <stdio.h>
int main(void)
{
FILE *filePointer;
filePointer = fopen("file.txt","w");
int i;
for(i=0; i > 400; i++)
{
fputs("%d, ",i,filePointer);
}
fclose(filePointer);
return(0);
}
No, there's no way that compiled without some serious-sounding warnings at least.
You're using fputs() as if it were fprintf(), passing it an integer instead of a FILE pointer (which the compiler should not allow) and an extra argument (which the compiler should not allow).
Also your for loop is broken. The middle part is an expression that should be true for as long as the loop should run, not the other way around.
You meant:
for(i = 0; i < 400; ++i)
{
fprintf(filePointer, "%d, ", i);
}
Also, you should check that the file really did open before assuming it did. I/O can fail.
Apart from the fputs() usage, the problem is:
for(i=0; i > 400; i++)
If you initialize a variable with zero and perform a loop as long as it's greater than 400, that won't last too long.
The fputs syntax seem wrong. I think it is:
int fputs(const char *str, FILE *stream)
Pick #unwind's approach (as mentioned above) but if you still want to use fputs then your fputs line should be expanded into 3 lines:
char temp[4]; // String to store 3-digit number + '\0'
sprintf(temp, "%d, ", i); // Prepare a string for a given number
fputs(temp, filePointer); // Write the string to the file
This should work. #happycoding :)
PS: You seem to be following a bit C++ standard in declaring a variable anywhere. It is not pure C. #justsaying

read csv file into 2-d array in c

I'm not familiar with C at all. I just need to input my data into an already well-developed model in C, put the data in arrays, get my output and put that output back into my program in Python. My data is in a CSV file and I'm just trying to put it in a 2-D array to run through some functions. When I run the following code to make sure I created my array, I get a random single value in the output that does not match the original data at all. Sometimes it prints 0.00000. I'm trying to view the entire array to make sure it's ready to be input.
Also, this is just a sample; my real data set will have >3000 rows. I understand I will need to use malloc() for this when I run my real data, correct?
#user3629249 thank you and #Cool Guy for all your comments. Here's what I have now. I think sprintf() is still having trouble converting my array values back to a float. I've searched all over and I still cant tell what I doing wrong but the error is telling me that data[l][k] and todata are still incompatible, could you tell me if I'm on the right track and what I'm doing wrong with the sprintf() function?
#include <stdio.h>
int main() {
FILE *fp;
fp=fopen("airvariablesSend.csv", "r");
if(fp == NULL){
printf("cannot open file\n\n");
return -1;
}
// Headers removed for simplicity. Still found in airvariables.csv to see which //column means what
float data[9][6]; //for putting into array
int k , l;
float num; //for using getline() function
char *memory;
int nbytes = 500;
// space for using malloc? Is this enough or too much?
char *token; //for parsing through line using strtok()
char *search = ","; //delimiter for csv
char *todata; //for
//asking for space on heap
memory = (char *) malloc (nbytes + 1);
// Don;t need to use realloc() because getline() does it automatically? //http://crasseux.com/books/ctutorial/getline.html
for(k = 0; k < 6 ; k++) //repeats for max number of columns
{
for (l=0; l< 9; l++) //modify for number of rows that you have
{
num = getline (&memory, &nbytes, fp); //reading line by line
token = strtok(num, search); //separating lines by comma in csv
//Apparently strtok() will only use whitespace and I'm getting warnings here too. Is there another function for separating by commas?
sprintf(todata, "%f", token);
data[l][k] = todata;
printf("%f\n", data[l][k]);
}
}
fclose(fp);
free(memory);
return 0;
}
Change
for (l=1; l< 11; l++)
To
for (l=0; l< 10; l++)
And
printf("%f\n", data[10][7]);
To
printf("%f\n", data[l][k]);
And move the printf just after
data[l][k] = num;
The former is done because array indices start from 0 and end at length-1.
The latter is done because you need to loop through the array to get each value that is stored in each index of the array and print it. You can't just use data[10][7] and expect the whole array to be printed. data[10][7] is an invalid location and accessing it invokes Undefined Behavior which means that anything can happen including segmentation faults, runtime errors, crashes etc.
Also, add a return -1; in the end of the body of the first if to end the execution of the program if the fopen failed to open its first argument.

Need help reading from a file in C

I have been looking around for a solution but cannot seem to find a solution to my question so I will ask it. I am working in C and am reading in a .txt and taking all the values and storing them in an array then doing various tasks with them. Now my problem is that no matter what I do I cannot get file pointer I create to point to the file for some reason. I have done this for projects in the past and have compared my code then to the current one and cannot see the issue. The filename needs to be read in from the command line as well. I think there is something wrong with what I'm passing through the command line but am not sure. I have stepped through and the filename is being passed correctly but when it tries to open I get a null pointer so there is just something I'm missing.
The text file will contain a series of numbers, the first number will be the number of numbers in the file after that first number. (So if the number is 10 then there will be ten numbers after 10 is read in) after that first number the remaining numbers will be 0-9 in a random order.
Below is my current chunk of code only involving reading of the file and storing its data. (I already know the array will be of size 10 which is why the array is declared with that size.)
int main(int argc, char *argv[])
{
char* filename = "numbers.txt";
int arr[10];
int numElem;
int indexDesired = 0;
FILE *fp;
fp = fopen(filename, "r"); // open file begin reading
if (!fp)
{
printf("The required file parameter name is missing\n");
system("pause");
exit(EXIT_FAILURE);
}
else
{
fscanf(fp, "%d", &numElem); //scans for the first value which will tell the number of values to be stored in the array
int i = 0;
int num;
while (i <= numElem) //scans through and gets the all the values and stores them in the array.
{
fscanf(fp, "%d", &num);
arr[i] = num;
i++;
}
fclose(fp);
}
}
***note: My sort and swap method work perfectly so I have omitted them from the code as the error happens before they are even called.
you said,
The filename needs to be read in from the command line as well.
However, you are using:
char* filename = "numbers.txt";
and
fp = fopen(filename, "r"); // open file begin reading
No matter what you are passing in the command line, the file you are trying to open is "numbers.txt".
Things to try:
Use the full path name of "numbers.txt" instead of just the name of the file.
char* filename = "C:\\My\\Full\\Path\\numbers.txt";
If that doesn't work, you will probably have to deal with permissions issues.
Pass the file name from the command line, using the full path. That should work if there are no permissions issues.
if ( argc < 2 )
{
// Deal with unspecified file name.
}
char* filename = argv[1];
Pass the relative path of the file name. If you are testing your program from Visual Studio, you have to make sure that you use the path relative to the directory from where Visual Studio launches your program.
while (i <= numElem)
should be
while (i < numElem)
Because in fscanf(fp, "%d", &numElem); you are scanning the number of elements.
Notice that the array in C starts from 0, so if say numElem is 10 arr[10] does not exist which can be harmful because arr goes from arr[0] to arr[9]
Also, you should check if numElem is lower than 10 before the while(i < numElem) loop.

Read from text file into char array[]

in my project I used arrays not pointers. My purpose is here copy all characters one-by-one from text.file into array. I found some examples from the Internet, this site but none of them was useful for me.
Think that input1.txt is "abcd" I want like these input1[0] = a, input1[1] = b, etc.
main ()
{
FILE *f1 = fopen("input1.txt", "r");
int i;
fseek(f1, 0, SEEK_END);
int inputsize = ftell(f1); //its about text's size
char input1[inputsize];
for(i = 0; i < inputsize; i++)
{
fscanf(f1, "%c", &input1[i]);
}
printf("%c ", input1[3]);
getchar();
}
When I run this code it doesn't print "d", but prints "6". Why is this happening? What should I do? Thanks for help
You seek to the end of the file to obtain it's size, but don't seek back to the start of the file again before you start actually reading it.
Insert just before your loop:
fseek(f1,0,SEEK_SET);
Pasting your code into my compiler with this amendment worked on my machine
You could also use a function rewind(FILE*) instead of doing an fseek() again.
Worth noting should be the fact that you're allocating an array with a variable, which might be a bad idea in this case (especially when you could be reading a bigger file than one with 4 characters).

Resources