I wrote this program for class. I have a problem with displaying what in the arry
all i get is symbols instead of a character even though i filled them with char from a file provided by the professor. please help me figure out what is the problem here i need it for tomorrow
// This program grades multiple choice exams1. Each exam consists of 20 questions.
//Each question has one of four possible answers: A, B, C, or D.
#include <stdio.h>
#include<stdlib.h>
#include <math.h>
const int maxsize = 20;
int fillArry (FILE *fi,char arry[],const int maxsize);
double gradeExam (char arry[], char studarry[],const int maxsize);
void desplayResults (double right);
int main ()
{
char arry[maxsize];
char studarry[maxsize];
int num,num1,i,right;
FILE *fi,*sd;
fi = fopen ("CorrectAnswers.txt","r");
if ( fi == NULL )
{
printf( "Error opening input file.\n\n" );
exit(1);
}
sd = fopen ("StudentAnswers.txt", "r");
if ( sd == NULL )
{
printf( "Error opening input file.\n\n" );
exit(1);
}
num = fillArry (fi,arry,maxsize);
num1 = fillArry (sd,studarry,maxsize);
for (i=0;i<maxsize;i++)
{
printf("%c\n",arry);
}
for (i=0;i<maxsize;i++)
{
printf("%c\n",studarry);
}
right = gradeExam (arry, studarry ,maxsize);
printf("you got %i right\n", right);
desplayResults (right);
return 0;
}
int fillArry (FILE *fi,char arry[],const int maxsize)
{
int u = 0;
while((fscanf(fi,"%c",&arry)==1 )&& u< maxsize)
{
u++;
}
return u;
}
double gradeExam (char arry[], char studarry[],const int maxsize)
{
int i, right=0, wrong=0;
for (i=1;i<=maxsize;i++)
{
if (arry[i]==studarry[i])
right++;
else
{
printf ("question number %i :%c is wrong, the correct answer is %c\n\n",i,studarry,arry);
wrong++;
}
}
printf("\nnumber of wrong answers: %i\n",wrong);
return right;
}
void desplayResults (double right)
{
double res;
res = (right/20)*100;
printf("You got %s %.2lf on the exam\n","%",res);
if (res<70)
printf ("You failed the exam\n");
else
printf ("You passed the exam\n");
}
The problem is with your fscanf statement. Try this out.
fscanf(fi,"%s",arry)
Also, for displaying the array contents, you have to do it like this :
for(i=0; i<maxsize; i++)
{
printf("%c",arry[i]);
}
EDIT1 : I have verified the same thing at my end and it is working. Please check the contents of the file CorrectAnswers.txt.
EDIT2 : I got the problem. It is in your print statement :
printf ("question number %i :%c is wrong, the correct answer is %c\n\n",i,studarry,arry);
Please correct it to :
printf ("question number %i :%c is wrong, the correct answer is %c\n\n",i,studarry[i],arry[i]);
Related
It should convert a string like this: Example: HEloOO, should be converted into : heLOoo . For some reason it doesn't work,it just wont convert the letters from uppercase to lowercase and vice versa any help would be appreciated ?
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void rek(char array[], int d)
{
int counter=0;
if(d==0)
{
printf("%s \n",array);
printf("%d \n",counter);
}
else
{
if((array[d]>='A' && array[d]<='Z')&&(array[d-1]>='A' && array[d-1]<='Z'))
{
array[d]=array[d]+32;
array[d-1]=array[d-1]+32;
counter++;
rek(array,d-2);
}
if((array[d]>='a' && array[d]<='z')&&(array[d-1]>='a' && array[d-1]<='z'))
{
array[d]=array[d]-32;
array[d-1]=array[d-1]-32;
counter++;
rek(array,d-2);
}
}
}
int main()
{
char array[100];
int d;
gets(array);
d=strlen(array);
rek(array,d);
return 0;
}
Your function does not call itself when two adjacent characters have different cases. Also you can get different results when the string is processed from the start or from the end.
I would write the function the following way
#include <stdio.h>
#include <ctype.h>
char * rek(char *s)
{
if (s[0] && s[1])
{
size_t i = 1;
if (islower((unsigned char)s[0]) && islower((unsigned char)s[1]))
{
s[0] = toupper((unsigned char)s[0]);
s[1] = toupper((unsigned char)s[1]);
++i;
}
else if (isupper((unsigned char)s[0]) && isupper((unsigned char)s[1]))
{
s[0] = tolower((unsigned char)s[0]);
s[1] = tolower((unsigned char)s[1]);
++i;
}
rek(s + i);
}
return s;
}
int main( void )
{
char s[] = "HEloOO";
puts(rek(s));
return 0;
}
The program output is
heLOoo
The main problem is that you recur only if your have a pair of upper-case or lower-case letters. Otherwise, you drop off the end of your if, return to the calling program, and quit converting things.
The initial problem is that you've indexed your string with the length. A string with 6 characters has indices 0-5, but you've started with locations 5 and 6 -- the final 'O' and the null character.
The result is that you check 'O' and '\0'; the latter isn't alphabetic at all, so you drop through all of your logic without doing anything, return to the main program, and finish.
For future reference, Here's the debugging instrumentation I used. Also see the canonical SO debug help.
#include<stdio.h>
#include<string.h>
#include<ctype.h>
void rek(char array[], int d)
{
int counter=0;
printf("ENTER rek %s %d\n", array, d);
if(d==0)
{
printf("%s \n",array);
printf("%d \n",counter);
}
else
{
printf("TRACE 1: %d %c%c\n", d, array[d-1], array[d]);
if((array[d]>='A' && array[d]<='Z')&&(array[d-1]>='A' && array[d-1]<='Z'))
{
printf("TRACE 2: upper case");
array[d]=array[d]+32;
array[d-1]=array[d-1]+32;
counter++;
rek(array,d-2);
}
if((array[d]>='a' && array[d]<='z')&&(array[d-1]>='a' && array[d-1]<='z'))
{
printf("TRACE 3: lower case");
array[d]=array[d]-32;
array[d-1]=array[d-1]-32;
counter++;
rek(array,d-2);
}
}
}
int main()
{
char *array;
int d;
array = "HEloOO";
d=strlen(array);
rek(array,d);
printf("%s\n", array);
return 0;
}
I come up with this dirty solution:
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
string solve(const string& str)
{
if (str.empty()) {
return "";
}
if (str.front() >= 'a' && str.front() <= 'z') {
return (char)toupper(str.front()) + solve(str.substr(1));
}
if (str.front() >= 'A' && str.front() <= 'Z') {
return (char)tolower(str.front()) + solve(str.substr(1));
}
}
int main()
{
string str;
cin >> str;
cout << solve(str) << endl;
return 0;
}
I want to scan to separate strings separated by a / using sscanf but it doesn't work. It works fine with a space.
For example, I want to separate the string 50%/60% into two strings like 50% and 60%.
You can have a look at code here:
#include <iostream>
using namespace std;
int extract_break_rewrites(int *m, int *n, const char *arg)
{
char m_str[10];
char n_str[10];
int err;
int count = sscanf(arg, "%s %s", n_str, m_str);
printf("%s %s %d\n",n_str, m_str,count);
if (count == 0) {
count = sscanf(arg, "/%s", m_str);
if (count == 0) {
*m = 0;
*n = 0;
return -1;
}
if (sscanf(m_str, "%d%%", m) != 1)
return -1;
}
else if (count == 1) {
if (sscanf(n_str, "%d%%", n) != 1)
return -1;
}
else if (count==2) {
if (sscanf(n_str, "%d%%", n) != 1)
return -1;
if (sscanf(m_str, "%d%%", m) != 1)
return -1;
}
return 1;
}
int main() {
int n,m;
const char * command = "50% 60%";
if (extract_break_rewrites(&m,&n,command)!=-1)
cout<<"Successful. The values of m and n are "<<m<<" and "<<n<<", respectively.\n";
else
cout<<"There was error in processing, may be input was not in the correct format.\n";
return 0;
}
You don't need to worry about what the code does, the important lines are 10, 11 and main function.
Try the following (assuming from stdin):
scanf("%[^/]/%s");
Use sscanf(buf, ...); if reading from a buffer.
The issue is that %s for scanf assumes that the string is followed by a space. This approach instructs scanf to find a string delimited by /, and then match the rest as a separate string.
EDIT: accidentally dropped the / in the scan string
Use a scan set
char a[100];
char b[100];
scanf("%[^/]/%s", a, b);
This scans in everything until it gets a /, then it starts and reads in a string.
You can also use std::strings and their facilities to achieve the same result:
#include <iostream>
#include <string>
using std::string;
using std::cout;
using std::stoi;
bool extract_break_rewrites(int &m, int &n, const string &arg) {
// find position of %/ in the string
string::size_type pos_first = arg.find("%/");
// check if the return value is valid (the substring is present and there
// is something else first)
if ( pos_first == string::npos || !pos_first ) // wrong input
return false;
string::size_type pos_2 = pos_first + 2,
pos_last = arg.find("%", pos_2);
if ( pos_last == string::npos || pos_last == pos_2 )
return false;
try {
m = stoi(arg.substr(0, pos_first));
n = stoi(arg.substr(pos_2, pos_last - pos_2));
}
// invalid argument or out of range
catch (...) {
return false;
}
return true;
}
int main() {
int n = 0, m = 0;
string command = "150%/60%";
if ( extract_break_rewrites(m, n, command) )
cout << "Successful. The values of m and n are "
<< m << " and " << n << ", respectively.\n";
else
cout << "There was error in processing, "
<< "maybe input was not in the correct format.\n";
return 0;
}
I'm very new at C++, maintaining my M.Sc on Information Systems. I have my first C++ homework announced and have been working on it for a couple of days. The aim of the code is simply to read info from a text file and print it on screen, then make calculation on some of it and print results to a new text file. However when I build, it gives the error:
EXC_BAD_ACCESS (code=EXC_I386_GBFLT)
in the first fscanf in readInfo function.
I know the code I wrote is not completely efficient but I just want it to print on screen and on output file correctly. I would really appreciate if anyone help me to resolve this error. I am about to freak out...
#include <stdio.h>
typedef struct {
char id[10];
char name[40];
float midterm;
float final;
int attendance;
}Student;
void readInfo(Student studentList[], int *count)
{
FILE *fin=fopen("scores.txt","r");
char surname = '\0';
*count=0;
while(!feof(fin))
{
fscanf(fin,"%c %c %c %f %f %d",studentList[*count].id, studentList[*count].name, &surname, &studentList[*count].midterm, &studentList[*count].final, &studentList[*count].attendance);
strcpy(studentList[*count].name, studentList[*count].name);
strcat(studentList[*count].name, " ");
strcat(studentList[*count].name, &surname);
*count++;
}fclose(fin);
printf("%-7s%17s %5.1f %5.1f %-2d\n", studentList[*count].id, studentList[*count].name, studentList[*count].midterm, studentList[*count].final, studentList[*count].attendance);
}
float studentScore(float midterm, float final, int attendance)
{
float score;
int maxAttend=0;
char id[10];
char name[40];
char surname[40];
FILE *fin=fopen("scores.txt","r");
while(!feof(fin))
{
fscanf(fin,"%c %c %c %f %f %d",id, name, surname, &midterm, &final, &attendance);
if(attendance>maxAttend)
maxAttend=attendance;
}fclose(fin);
score=midterm*0.3+final*0.5+(maxAttend/20)*attendance;
return score;
}
float avgScore(Student studentList[])
{
float average;
int count;
int totalScore=0;
readInfo(studentList, &count);
for(int i=0; i<=count; i++)
{
totalScore+=studentScore(studentList[count].midterm, studentList[count].final, studentList[count].attendance);
}
average=totalScore/count;
return average;
}
void courseGradeOutput(Student studentList[])
{
FILE *fout=fopen("output.txt","w");
int count;
int pass=0;
float score;
char letterGrade[2];
float avg;
fprintf(fout,"\tId\tName, Surname = (Score, Letter)\n");
readInfo(studentList, &count);
for(int i=0; i<=count; i++)
{
score=studentScore(studentList[i].midterm, studentList[i].final, studentList[i].attendance);
if(score>=0 && score<=49)
{ letterGrade[0]={'F'};
letterGrade[1]={'F'};}
else if (score>=50 && score<=59)
{letterGrade[0]={'F'};
letterGrade[1]={'D'};}
else if (score>=60 && score<=64)
{letterGrade[0]={'D'};
letterGrade[1]={'D'};}
else if (score>=65 && score<=69)
{letterGrade[0]={'D'};
letterGrade[1]={'C'};}
else if (score>=70 && score<=74)
{letterGrade[0]={'C'};
letterGrade[1]={'C'};}
else if (score>=75 && score<=79)
{letterGrade[0]={'C'};
letterGrade[1]={'B'};}
else if (score>=80 && score<=84)
{letterGrade[0]={'B'};
letterGrade[1]={'B'};}
else if (score>=85 && score<=89)
{letterGrade[0]={'B'};
letterGrade[1]={'A'};}
else if (score>=90 && score<=100)
{letterGrade[0]={'A'};
letterGrade[1]={'A'};}
if(score>=60)
pass++;
fprintf(fout,"%7s %16s = ( %4.1f, %6s\n)", studentList[i].id, studentList[i].name, score, letterGrade);
}
avg=avgScore(studentList);
fprintf(fout,"\nSome statistics:\n\nClass Avg Score: %5.2f \n #Students: %11d \n #Passed Students: %4d \n #Failed Students: %4d",avg,count,pass,(count-pass));
fclose(fout);
}
int main()
{ Student studentList[100];
int count;
readInfo(studentList, &count);
courseGradeOutput(studentList);
}
Screenshot
The crash is most likely caused by either fscanf followed by strcpy and/or by your increment of count inside readInfo.
You write *count++, but this is equivalent to
count = count + 1;
*(count-1);
What you want is (*count)++.
The fscanf scans characters %c where you want to scan strings %s (for id and name). You also want to scan surname as a string, probably, but then you need to change surname to be a character array:
char surname[30];
*count=0;
while(!feof(fin))
{
fscanf(fin,"%s %s %s %f %f %d",studentList[*count].id, studentList[*count].name, surname, &studentList[*count].midterm, &studentList[*count].final, &studentList[*count].attendance);
strcat(studentList[*count].name, " ");
strcat(studentList[*count].name, surname);
(*count)++;
}
fclose(fin);
I also removed the first strcpy as you were copying from a buffer to itself, which is not allowed.
I haven't checked the other functions thoroughly, but I do notice that you do not use the result from your readInfo called from main when you do courseGradeOutput: this function calls readInfo again. You could modify it to take the read student records and the count, so you don't have to read the file again.
You might also want to improve scanf a bit to pass a width, such as %29s for name, to avoid overflowing the buffer when the name inside the file is too long; and the same for the other strings you scan. You should then also look at the return value of fscanf and only use the things you scanned when it succeeded in scanning every argument.
new to C and trying to read in a text file, "stocks", delimited with vertical line '|' characters. Aim is to open the file which is has a string and float value on each line, in the format:
TOM|149.62
JIM|23.25
I have read other posts about commas, colon and tab delimited files, but the "scanset" suggestion applied here as a [^|] between the %s and %f doesn't seem to work. I seem to have managed to store the first character of the string at least now, but the float value saved is nonsense. This will later be writing to the arrays declared after the file but the basic case of displaying the string and float value for each line means I can continue on my own. Appreciate any help you can give me.
#include <iostream>
#include<stdlib.h>
#include<stdio.h>
using namespace std;
// TOM|149.62
// JIM|23.25
int main()
{
FILE *stocks;
char *stock_Tickers[100];
float stock_Prices[100];
if ((stocks = fopen("Stocks.txt", "r")) == NULL)
{
fprintf(stderr, "Error opening file.\n");
exit(1);
}
char tempchar;
float tempfloat;
for (int i = 0; i < sizeof (stock_Tickers); i++)
{
if (feof(stocks))
{
break;
}
fscanf(stocks, "%s[^|]%f\n",&tempchar,&tempfloat);
cout << tempchar << " " << tempfloat;
cin.get();
}
return 0;
}
Update: #Michel Billaud Apologies, but I have one last error here. Your method worked perfectly, but when I try it on this slight variant it starts printing rubbish on the last floating point and breaks on subsequent loops. Looked at the local variables and the last array just isn't updating. I think it has to do with the new line, as when I change the float for an integer it still doesn't work. Can you see what I might be doing wrong as it seems the same format to me? Format this time is Ryan|B|IBM|100|176.10. All files are read in after this...Thanks.
FILE *trades;
// Ryan|B|IBM|100|176.10
// Ryan|S|IBM|50|177.10
char trade_User[100][20];
char trade_Type[100];
char trade_Tickers[100][4];
int trade_Quantity[100];
float trade_Prices[100];
int trade_Count = 0;
if ((trades = fopen("Trades.txt","r")) == NULL)
{
fprintf(stderr, "Error opening file.\n");
exit(1);
}
for (int i = 0; i < sizeof(trade_Tickers); i++)
{
if (feof(trades))
{
break;
}
fscanf(trades, "%19[^|]|%1[^|]|%4[^|]|%d[^|]|%f\n",
&trade_User[i], &trade_Type[i], &trade_Tickers[i], &trade_Quantity[i], &trade_Prices[i]);
printf("%s %c %s %d %f\n",
trade_User[i], trade_Type[i], trade_Tickers[i], trade_Quantity[i], trade_Prices[i]);
trade_Count++;
}
Hint: when trying to use a problematic feature, do it in a small separate program. So you won't take the risk to draw wrong conclusions because of another unrelated issue.
// just playing with |-separated fields
#include <stdio.h>
int main(int argc, char **argv)
{
char line[]="TOM|1234.56";
char name[20];
float value;
sscanf(line, "%[^|]|%f", name, &value);
printf("name = %s, value = %f\n", name, value);
return 0;
}
By the way: seems you're using the C++ compiler (because of "using namespace std").
I have a program, that asks several strings and should sort them.
My code is:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX_STR_LEN 256
int myStrCmp (const void * a, const void * b)
{
return strcmp((const char *)a, (const char *)b);
}
int main(void)
{
int strNum; // expected number of input strings
int strCnt; // counter of strings
char ** storage; // pointr to the memory when strings are stored
char strBuf[ MAX_STR_LEN]; // buffer for strings
char * strPtr;
// input of strings number
do{
printf("How many strings will be entered: ");
while( scanf("%d", &strNum) != 1)
{
printf("ERROR: Not number was entered!\n");
while( getchar() != '\n' );
printf("Please enter a number: ");
}
if( strNum < 2 )
{
printf("ERROR: Number less than 2 was entered!\n");
}
while( getchar() != '\n' );
}
while(strNum < 2);
// allocation of memory for pointers
storage = (char **) calloc(strNum, sizeof(char*) );
if( storage == NULL )
{
printf("ERROR: Unexpected problems with memory allocation!\n");
return 1;
}
// input of strings
for( strCnt = 0; strCnt < strNum; strCnt++)
{
printf("Enter string #%d:\n", strCnt + 1);
fgets(strBuf, MAX_STR_LEN, stdin);
strPtr = strchr(strBuf, '\n');
if( strPtr )
{
*strPtr = '\0';
}
else
{
strBuf[ MAX_STR_LEN - 1] = '\0';
}
// allocation memory for particular string
storage[strCnt] = (char *) malloc(strlen(strBuf) + 1);
if(storage[strCnt] == NULL)
{
printf("ERROR: Unexpected problems with memory allocation!\n");
return 2;
}
// move string to dynamic memory
strcpy(storage[strCnt], strBuf);
}
// sort the strings
qsort(storage, strNum, sizeof(char**), myStrCmp);
// output the result
printf("\nSorted strings:\n");
for( strCnt = 0; strCnt < strNum; strCnt++)
{
printf("%s\n", storage[strCnt]);
}
return 0;
}
The simplest test shows the trouble:
How many strings will be entered: 3
Enter string #1:
ddd
Enter string #2:
aaa
Enter string #3:
ccc
Sorted strings:
ddd
aaa
ccc
I have tryed Visual C++ and gcc, but the result is the same. Please, say me what is wrong in the code?
The problem is in myStrCmp function.
Because a and b are elements in not a simple array, but in array of pointers, their type must be char ** and function that compares two elements have to be as follows:
int myStrCmp (const void * a, const void * b)
{
return strcmp(*(const char **)a, *(const char **)b);
}