I want to implement bubble sort with writing to the file. I think that sorting is implemet good, but something wrong is with writing to file.
int main(int argc, char *argv[])
{
FILE *fp;
int tab[] = {3,5,1,2,4};
int i, j, temp;
if ((fp=fopen("test.txt", "w"))==NULL) {
printf ("Error!\n");
exit(1);
}
for(i =0; i<5;i++)
{
for(j=0; j<4; j++)
{
if(tab[j] > tab[j+1])
{
temp = tab[j+1];
tab[j+1] = tab[j];
tab[j] = temp;
}
}
}
fprintf (fp, "%d", tab);
fclose (fp);
return 0;
}
Can you help me?
Since %d format string instructs printf() to print a single integer what the code tries to do is writing a pointer to an array of integers as if it was an integer.
Simply loop over your array and print one int in every iteration. You will also need to decide on a separator you want to use or else all the integers will be written side by side preventing the reader from making sense of them.
Related
This is a function that is trying to perform the first step of converting a CFG to Chromsky Normal From by adding 0->S as a rule to the end of the list of rules. My rules are an array of characters. For some reason it will only print the array the first time and not any time after that. I want it to print the input and then result once the array has been edited. I cannot figure out why it won't print. The output is just the original input and then blank spaces.
UPDATE: It will now print both times, but the output of the second print is the same as the first. It is not registering that I added ',','0','>','S' as elements to the array. Am I adding the elements wrong?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//global variables
char stringCFG[200];
//a program to convert CFG to Chromsky Normal Form
int main(int argc, char *argv[]){
//intialize instance variables
FILE *CFG;
FILE *output;
char ch;
int RHS= 0;
int isThereS= 0;
int howManyItems= 0;
CFG= fopen(argv[1], "r");
output= fopen(argv[2], "w");
for (int i=0; i<200; i++){
fscanf(CFG, "%c", &stringCFG[i]);
howManyItems++;
fprintf(output,"%c", stringCFG[i]);
}
printf("\n");
for(int i=0; i<200; i++){
if(stringCFG[i] == '>'){
RHS= 1;
}
if(stringCFG[i] == ','){
RHS= 0;
}
if(RHS== 1){
if(stringCFG[i] == 'S'){
isThereS=1;
}
}
}
if(isThereS==1){
stringCFG[howManyItems]= ',';
howManyItems++;
stringCFG[howManyItems]='0';
howManyItems++;
stringCFG[howManyItems]='>';
howManyItems++;
stringCFG[howManyItems]='S';
howManyItems++;
}
for(int i=0; i<200; i++){
fprintf(output,"%c",stringCFG[i]);
}
fclose(CFG);
fclose(output);
}
The problem seems to be here:
for (int i=0; i<200; i++){
fscanf(CFG, "%c", &stringCFG[i]);
howManyItems++;
fprintf(output,"%c", stringCFG[i]);
}
This loop always executes 200 times regardless of what is in the file. In other words - the value of howManyItems will be 200 when the loop is done.
You can check that simply by printing howManyItems after the loop, i.e.
printf("After loop, howManyItems=%d\n", howManyItems);
Since you have:
char stringCFG[200];
then
stringCFG[howManyItems]= ','; // bad.. writing to stringCFG[200]
howManyItems++;
stringCFG[howManyItems]= '0'; // bad.. writing to stringCFG[201]
howManyItems++;
...
will write outside of the array. That is undefined behavior.
You need to stop the first loop once the whole file has been read. Something like:
for (int i=0; i<200; i++){
if (fscanf(CFG, "%c", &stringCFG[i]) != 1)
{
// No more data
break;
}
howManyItems++;
fprintf(output,"%c", stringCFG[i]);
}
and all the following loops must then use howManyItems as the upper limit.
Like
for(int i=0; i<howManyItems; i++){
if(stringCFG[i] == '>'){
RHS= 1;
}
...
}
BTW: Since you want to be able to add 4 extra chars, you probably should do:
char stringCFG[200]; --> char stringCFG[200 + 4];
BTW: Hard-coding the value 200 over and over again is bad practice. Instead use a define like:
#define MAX_CHARS 200
and replace all the hard-coded 200 with MAX_CHARS. Then you can adjust the maximum simply by editing one line instead of multiple lines.
It seems like I didn't quite understand how the file stream works. My text file right now contains the following integers: 1 10 5 4 2 3 -6, but I would like the program to be able to read any number of integers from the file, should it change.
Apparently I'm not even using the correct functions.
The code I have written is the following:
int main() {
printf("This program stores numbers from numeri.txt into an array.\n\n");
int a[100];
int num;
int count = 0;
FILE* numeri = fopen("numeri.txt", "r");
while (!feof(numeri)) {
num = getw(numeri);
a[count] = num;
if (fgetc(numeri) != ' ')
count++;
}
int i;
for (i = 0; i < count; i++) { printf("%d ", a[i]); }
return 0;
}
I would like it to print out the array with the stored numbers, but all I get is: 540287029 757084960 -1
Can someone help me understand what I did wrong and maybe tell me how to write this kind of code properly?
I have fixed your code based on comments. I used fscanf to read from file and limited the amount of numbers that can be stored in array by checking count < 100 and checking whether fscanf filled exactly one argument.
Also, I checked that whether file could be opened or not, just for safety. If it couldn't be opened, then just print error message and return 1.
int main() {
printf("This program stores numbers from numeri.txt into an array.\n\n");
int a[100] = {0};
int num;
int count = 0;
int i = 0;
FILE* numeri = fopen("numeri.txt", "r");
if (numeri == NULL) {
printf("Can't open file\n");
return 1;
}
while (count < 100 && fscanf(numeri, "%d", &num) == 1) {
a[count++] = num;
}
for (i = 0; i < count; i++) { printf("%d ", a[i]); }
return 0;
}
I'm working on a program for my Intro to C class that requires me to write a program that solves jumble puzzles (you know, those anagram puzzles you see in the newspaper), based on a dictionary text file that my professor gave us. It alphabetizes words from the dictionary, takes in jumbles from a text file (called "jumble.txt"), alphabetizes those, then runs a string compare to find a match. I've got all the code written, but it immediately crashes when I try to run it, and I can't figure out why. I thought maybe the Stackoverflow users might be able to help me out here.
Here's the code I have:
#include <stdio.h>
#include <strings.h>
#define MAX_WORD_LEN 6
#define MAX_NUM_WORDS 30000
typedef struct {
char word[MAX_WORD_LEN+1];
char sort[MAX_WORD_LEN+1];
} jumble_type;
void bubblesort(char letters[], int length);
int main () {
int words, jumbles;
int j, q;
jumble_type list[MAX_NUM_WORDS];
jumble_type list2[MAX_NUM_WORDS];
// Creating file pointers
FILE *ifp;
FILE *ifp2;
//Opens Jumble and dictionary files and reads the info from them
ifp = fopen("jumbledct.txt", "r");
ifp2 = fopen("jumble.txt", "r");
//Assigns the value of "words" to the first line of jumbledct.txt
fscanf(ifp, "%d", words);
//Assigns the value of "jumbles" to the first line of jumble.txt
fscanf(ifp2, "%d", jumbles);
// Reads the words from the dictionary into the "word" section of our
// list structure.
int i;
for (i = 0; i < words; i++){
fscanf(ifp, "%s", &list[i].word);
strcpy(list[i].sort, list[i].word);
bubblesort(list[i].sort, strlen(list[i].sort));
printf("%s\n", list[i].sort);
}
//Reads from Jumble.txt
for (i = 0; i < jumbles; i++){
fscanf (ifp2, "%s", &list2[i].word);
strcpy(list2[i].sort, list2[i].word);
bubblesort(list2[i].sort, strlen(list2[i].sort));
//printf("%s\n", list2[i].sort);
}
for(j=0;j<jumbles; j++){
printf("JUMBLE PUZZLE # %d: %s\n", j+1, list2[j].word);
int x=0;
for (q = 0; q < words; q++){
if(strcmp(list2[j].sort, list[q].sort)==0){
printf("%s\n", list[q].word);
x++;
}
}
if (x == 0){
printf("Sorry, this puzzle has no solutions. \n\n");
}
printf("\n");
}
return 0;
}
void bubblesort(char letters[], int length) {
char temp;
int x, y;
for(x = 0; x < length; x++){
for (y = x; y < length; y++){
if (letters[x] > letters[y]){
temp = letters[y];
letters[y] = letters[x];
letters[x] = temp;
}
}
}
}
Thanks in advance for all your help.
My C is a little rusty, but shouldn't the third argument to the fscanf function be an address (like &words and &jumbles)?
EDIT:
void print(const int *v, const int size) {
FILE *fpIn;
fpIn = fopen("char-array.txt", "a");
int i;
if (v != 0) {
for (i = 0; i < size; i++) {
printf("%d", (int)v[i]);
fprintf(fpIn, "%d\n", (int)v[i]);
}
perm_count++;
printf("\n");
}
fclose(fpIn);
}
I guess this is a relatively simple question :)
Basically the program is using a permutation algorithm, and printing the output to standard output in the console. I also want to write the content to a file via fprintf I assume. Though I cant seem to get it working. It just prints garbage characters into the first line in the text file and nothing more !
I will paste the code below, and help is much appreciated ! The write to file code is found within the print function.
Thanks,
T.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <time.h>
clock_t startm, stopm;
#define START if ( (startm = clock()) == -1) {printf("Error calling clock");exit(1);}
#define STOP if ( (stopm = clock()) == -1) {printf("Error calling clock");exit(1);}
#define PRINTTIME printf("%2.3f seconds used by the processor.", ((double)stopm- startm)/CLOCKS_PER_SEC);
int perm_count = 0;
void print(const int *v, const int size) {
FILE *fpIn;
fpIn = fopen("char-array.txt", "wb");
int i;
if (v != 0) {
for (i = 0; i < size; i++) {
printf("%d", (char)v[i]);
fprintf(fpIn, "%d", v[i]);
fprintf(fpIn, "\n");
}
perm_count++;
printf("\n");
}
}
void permute(int *v, const int start, const int n) {
int i;
if (start == n-1) {
print(v, n);
}
else {
for (i = start; i < n; i++) {
int tmp = v[i];
v[i] = v[start];
v[start] = tmp;
permute(v, start+1, n);
v[start] = v[i];
v[i] = tmp;
}
}
}
int main() {
int i, x;
printf("Please enter the number of terms: ");
scanf("%d", &x);
int arr[x];
printf("Please enter the terms: ");
for(i = 0; i < x; i++)
scanf("%d", &arr[i]);
START
permute(arr, 0, sizeof(arr)/sizeof(int));
STOP
printf("Permutation Count: %d\n", perm_count);
PRINTTIME
return 0;
}
1. Incorrect access modes in fopen call
You open your file as a binary file: fopen("char-array.txt", "wb");. Don't put b to this string containing access modes if you are going to write formatted strings there. And since you probably want to append new data at the end of the file instead of overwritting them, use a instead of w:
fopen("char-array.txt", "a");
2. Writing to the output buffer, not directly into the file
When you are using functions like fprintf, you don't write directly to the file but to the output buffer. You have to use fflush to write data from the output buffer into the file, or you can just close your file by using fclose function which flushes this buffer automatically.
Just add this line:
fclose(fpIn);
at the end of print function.
3. Incorrect formatting of the output
You should not cast int to char. It will truncate your numbers. And you also have fprintf(fpIn, "\n"); in wrong scope I guess. It could look like this:
for (i = 0; i < size; i++) {
printf("%d ", v[i]);
fprintf(fpIn, "%d ", v[i]);
}
perm_count++;
printf("\n");
fprintf(fpIn, "\n");
Don't waste your time doing programming you don't have to, the use of fprintf is nice but since all you want to do is print the output, you can just print things into the file directly using UNIX built-in commands. Say your program is called wirteoutput then all you have to do is pass the following command when calling it from the shell writeoutput > file.txt. All you would have to use would be the printf function.
If you are curious about this, this is an old function and you can find a detailed description in the original paper The UNIX Operating System. Look at the section called Standard I/O.
You didn't cast to a char (from a int) when you wrote to the file as you did with the screen display. The following will provide the same numbers in the file as you're seeing on screen:
fprintf(fpIn, "%d", (char)v[i]);
getLine is a function that gets a line, I'm trying to combine lines together outside the getLine function. When ever I try doing this in a loop it messes up the output. I bet it has to do with the pointers, but I have spend many hours trying to figure it out.
int num;
int matrix[370];
i=1;
j=0;
while(*(point=getLine(infile)) != -2){
n[j]=*point;
if(n[0] != n[j]){
printf("matrix dim error 1");
break;
}
while (i<=n[j]){
matrix[i+(3*j)] = *(point+(i+(3*j)));
i++;
printf("%d", matrix[i+(3*j)]);
}
printf("%d %d %d\n", matrix[1],matrix[2],matrix[3]);
j++;
}
fclose( infile );
}
int *getLine(FILE *infile){
int l=0;
int line[7];
int i=1;
int *point;
while ((l=getNum(infile)) != -1){
if(l==EOF){
line[0]=EOF;
point = &line[0];
return(point);
}
line[i]=l;
i++;
}
if(i==1){
line[0]=-2;
point = &line[0];
return(point);
}
line[0]=(i-1); //stores the length of the line in first space
printf("%d %d %d\n",line[1],line[2],line[3]);
point = &line[0];
printf("%d\n",*point);
return(point);
}
int getNum(FILE *infile) {
int c=0;
int value=0;
while ((c=fgetc(infile)) != '\n') {
if(c==EOF){
return(EOF);
}
if((c==32)||(c==13)){
if(value != 0){ //Making sure a number has been gotten
//printf("%d\n\n", value);
return(value);
}
//otherwise keep getting characters
}
else if ((c<=47)||(c>=58)){
printf("incorrect number input %d\n", c);
exit(1);
}
else {
value = (10*value) + (c - '0');
}
}
return(-1);//flags that the end of line has been hit
}
There is one problem:
int *getLine(FILE *infile){
int line[7];
int *point;
point = &line[0];
return(point);
}
You return a pointer to a local variable. It becomes invalid when you return from the function. You could allocate it instead on the heap, or let the caller provide it as an argument.
Instead of
while (i<=n[j]){
didn't you mean
while (i<=n[j][0]){
More Edit: That's actually ok, i overlook the * in the assignment.
Edit: Some more things:
there is no check that the range of int is not exceeded in getNum
there is no check in getLine that more than 7 values are read (which would blow int line[7]
the matrix calculation in my opinion assumes that there are 3 values read, getLine can deliver up to 7
matrix[i+(3*j)] = *(point+(i+(3*j))); ?? point is only 7 int big!!! so for the second value it will read beyond defined data. Shouldn't it read matrix[i+(3*j)] = point[i];
hth
Mario
BTW: I strongly recommend:
resort to std-lib functions
better naming (i and j in the same source are strongly discouraged)