getting the value, which a pointer is pointing to - c

I am having some trouble with an assignment. I am trying to read the lines from a txt file (line by line) split the values and calculate the quadratic formula from them; the lines always contain a, b and c. However, I came to a problem where it looks like when I come to the formula the values seem to be the pointer position instead of the value assigned. I don't think the finalArrayOfValues should be a char* but the code wouldn't compile without it. Is there any way to retrieve the value from the pointer or should I try a different solution?
Apologies in advance if this is trivial (coming from javascript and python) I am quite new to c,
Thank you.
#include <math.h>
#include <stdio.h>
#include <string.h>
int main(void) {
double a;
double b;
double c;
double d;
char arrayOfValues[100][128];
char lines[128];
char *finalArrayOfValues[3];
int i = 0;
double root1, root2;
FILE *file; /* declare a FILE pointer */
file = fopen("QFData1.txt", "r");
int count = 0;
while (fgets(lines, 128, file)) {
strcpy(arrayOfValues[count], lines);
printf("line %d: %s\n", count, arrayOfValues[count]);
count++;
}
char *string = arrayOfValues[1];
char *token = strtok(string, ",");
// loops through the string to extract all other tokens
for (int n = 0; n < 3; n++) {
finalArrayOfValues[i] = token;
printf(" %s\n", token);
token = strtok(NULL, ",");
i++;
}
printf(" %s\n", finalArrayOfValues[0]);
printf(" %s\n", finalArrayOfValues[1]);
printf(" %s\n", finalArrayOfValues[2]);
a = finalArrayOfValues[0] - "0";
b = finalArrayOfValues[1] - "0";
c = finalArrayOfValues[2] - "0";
printf(" %f\n", a);
printf(" %f\n", b);
printf(" %f\n", c);
d = b * b - (4 * a * c);
printf(" %f\n", d);
// real roots
root1 = (-b + sqrt(d)) / (2 * a);
root2 = (-b - sqrt(d)) / (2 * a);
printf("First root = %.2lf\n", root1);
printf("Second root = %.2lf\n", root2);
return 0;
}

Related

How can I print out scanned in structure to file properly? (C)

I am trying to read from 2 files (f1.txt and f2.txt) using structures and print them out to the third file (f3.txt), but I seem to be getting some errors. Issues did not occur before I tried printing out the values to the file (fprintf command), and I cant seem to find a way to fix it..
This is for a homework assignment, but since I've been struggling to fix this issue for months now (yes, I'm pretty bad), I thought maybe anyone here knows how I can fix this.
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define MAX_NIME_PIKKUS 100
#define MAX_AINE_PIKKUS 100
#define MAX_KOOD 10
#define MAX_HINNE 5
#define DEBUG 0
int n;
int m;
struct Tudeng{
char Nimi[MAX_NIME_PIKKUS];
char Kood[MAX_KOOD];
};
struct Tudeng *pTudeng;
struct Aine{
char Nimetus[MAX_AINE_PIKKUS];
char aineKood[MAX_KOOD];
};
struct Aine *pAine;
struct Tud{
char Tudengikood[MAX_KOOD];
int Hinne[MAX_HINNE];
};
struct Tud *pTud;
char f1[] = "f1.txt";
char f2[] = "f2.txt";
char f3[] = "f3.txt";
FILE *fp1,*fp2,*fp3;
int sisendf1_kontroll();
int sisendf2_kontroll();
void tekita_failid();
void andmed_failidesse(char Tudeng1, char Tudeng2, char Aine1, char Aine2, char Tud1, int Tud2);
int main(void){
int a;
int b;
int c;
n = sisendf1_kontroll();
printf("Failist %s loeti %d tudengi andmed.\n", f1, n);
m = sisendf2_kontroll();
printf("Failist %s loeti %d aine andmed.\n", f2, m);
fp1 = fopen(f1,"r");
fp2 = fopen(f2, "r");
int i = 0;
a = sizeof(struct Tudeng);
b = sizeof(struct Aine);
c = sizeof(struct Tud);
pTudeng = malloc(a * n);
pAine = malloc(b * m);
pTud = malloc(c * m);
if(DEBUG)printf("Struktuuri Tudeng baidi aadress on %p, ühe kirje andmeteks eraldati mälu %d baiti, mälu eraldati massiivile kokku %d baiti \n", pTudeng, a, a * n);
if(DEBUG)printf("Struktuuri Aine baidi aadress on %p, ühe kirje andmeteks eraldati mälu %d baiti, mälu eraldati massiivile kokku %d baiti \n", pAine, b, b * m);
if(DEBUG)printf("Struktuuri Tud baidi aadress on %p, ühe kirje andmeteks eraldati mälu %d baiti, mälu eraldati massiivile kokku %d baiti \n", pTud, c, c * m);
int loopiks;
while(loopiks == 0){
while(!feof(fp1)){
fscanf(fp1,"%s",(pTudeng+i)->Nimi);
fscanf(fp1,"%s",(pTudeng+i)->Kood);
i++;
}
while(!feof(fp2)){
fscanf(fp2,"%s",(pAine+i)->Nimetus);
fscanf(fp2,"%s",(pAine+i)->aineKood);
fscanf(fp2,"%s",(pTud+i)->Tudengikood);
fscanf(fp2,"%d",(pTud+i)->Hinne);
i++;
}
loopiks = 1;
tekita_failid();
andmed_failidesse((pTudeng+i->Nimi), (pTudeng+i)->Kood, (pAine+i)->Nimetus, (pAine+i)->aineKood, (pTud+i)->Tudengikood, (pTud+i)->Hinne);
free(pTudeng);
free(pAine);
free(pTud);
}
//fprintf(fp3, "%s %s\n",(pTudeng+i)->Nimi,(pTudeng+i)->Kood);
fclose(fp1);
fclose(fp2);
return 0;
}
int sisendf1_kontroll(void){
char rida[122];
int n = 0, p;
fp1 = fopen(f1,"r");
if(fp1 == NULL){
printf("Sisendfaili %s avamine ebaonnestus!", f1);
exit(1);
}else{
while(!feof(fp1)){
fgets(rida, 122, fp1);
p = strlen(rida);
if (p > 1) n++;
}
}
fclose(fp1);
return n;
}
int sisendf2_kontroll(void){
char rida2[122];
int m = 0, o;
fp2 = fopen(f2,"r");
if(fp2==NULL){
printf("Sisendfaili %s avamine ebaonnestus!", f2);
exit(1);
}else{
while(!feof(fp2)){
fgets(rida2, 122, fp2);
o = strlen(rida2);
if (o > 1) m++;
}
}
fclose(fp2);
return m;
}
void tekita_failid(){
fp3 = fopen(f3, "w");
fclose(fp3);
return;
}
void andmed_failidesse(char Tudeng1, char Tudeng2, char Aine1, char Aine2, char Tud1, int Tud2){
fp3 = fopen(f3, "a");
int i;
int j;
while(i < n && j < m){
for(i = 0; i < n; i++){
fprintf(fp3, "%s %s ",(pTudeng+i)->Nimi,(pTudeng+i)->Kood);
}
for(j = 0; j < m; j++){
fprintf(fp3, "%s %s %s %d \n",(pAine+i)->Nimetus,(pAine+i)->aineKood, (pTud+i)->Tudengikood, (pTud+i)->Hinne);
}
}
return;
}
I expected the program to output the information from f1.txt and f2.txt to f3.txt, but currently compiler tells me that I cannot do that, since I'm using * int in last function, but it says that regular int is required.
Compiler is right:
andmed_failidesse expects an int as last parameter and you're passing Hinne which is an array of int, aka int*.
As Tud2 is not used anyway in your current code you can remove it from function signature or rework your function to use it.
Your compiler should also warn you that you have other unused parameters in your function.
It is obviously a work in progress: take a break, re-read your C courses and try to figure out what your function is supposed to do, and which parameters it needs.

Crashing issue, might be due to a for loop

My program keeps crashing while I run it. I have isolated parts of it (using /**/) to try and figure out what the issue is, and I think it has something to do with the second for loop in my sort function, since isolating that prevents the crashing. However, I've tried fixing it in several different ways (using while/do loops instead, etc), but it manages to keep crashing. Ive also looked at the parameters and how I declared it in main, but I can't see an issue with that. Knowing me, its probably something really dumb ive been missing for hours trying to fix this. Any help would be greatly appreciated
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 5
struct student
{
char name[20];
int hw1, hw2, hw3, ex1, ex2, totalhw, totalex;
float classperc;
char grade;
};
void student_info(struct student s[], int n, int *classex1, int *classex2, int *a, int *b, int *c, int *d, int *f)
{
for (int i = 0; i < n; i++)
{
printf("\n\nPlease enter the student's name:\n");
gets_s(s[i].name, 20);
printf("\nPlease enter the student's homework grades:\n");
scanf("%d %d %d", &(s[i].hw1), &(s[i].hw2), &(s[i].hw3));
printf("\nPlease enter the student's exam scores:\n");
scanf("%d %d", &(s[i].ex1), &(s[i].ex2));
getchar();
s[i].totalhw = s[i].hw1 + s[i].hw2 + s[i].hw3;
s[i].totalex = s[i].ex1 + s[i].ex2;
*classex1 += s[i].ex1;
*classex2 += s[i].ex2;
s[i].classperc = ((float)s[i].totalhw / 1.875) + ((float)s[i].totalex / 3.333);
if (s[i].classperc >= 90)
{
*a = *a + 1;
s[i].grade = 'A';
}
else if (s[i].classperc >= 80)
{
*b = *b + 1;
s[i].grade = 'B';
}
else if (s[i].classperc >= 70)
{
*c = *c + 1;
s[i].grade = 'C';
}
else if (s[i].classperc >= 60)
{
*d = *d + 1;
s[i].grade = 'D';
}
else
{
*f = *f + 1;
s[i].grade = 'F';
}
}
}
void sort(struct student s[], int n)
{
struct student temp;
for (int i = 0; i < SIZE - 1; i++)
{
for (int j = i + 1; j< SIZE; j++)
{
if (strcmp(s[i].name, s[j].name) > 0)
{
temp = s[i];
s[i] = s[j];
s[j] = temp;
}
}
}
for (int i = 0; i < n; i++)
{
printf("\nStudent: %s\nThe Three Homework Scores: %d %d %d\nThe Two Exam Scores: %d %d\n", s[i].name, s[i].hw1, s[i].hw2, s[i].hw3, s[i].ex1, s[i].ex2);
printf("Total Homework Score: %d\nTotal Exam Score: %d\nClass Percentage: %f Grade: %s", s[i].totalhw, s[i].totalex, s[i].classperc, s[i].grade);
// It crashes right before executing this second printf statement (I have no idea why :[)
}
}
void avg_exams(int classex1, int classex2, float *avgex1, float *avgex2)
{
*avgex1 = classex1 / (float)5;
*avgex2 = classex2 / (float)5;
}
void print_classinfo(float avgex1, float avgex2, int a, int b, int c, int d, int f)
{
printf("\n\nThe Average Exam Score for Exam 1 is: %0.2f\nThe Average Exam Score for Exam 2 is: %0.2f\n", avgex1, avgex2);
printf("There were %d A's, %d B's, %d C's, %d D's, %d F's in the class overall\n\n", a, b, c, d, f);
}
void main()
{
struct student s[SIZE];
int a, b, c, d, f , classex1, classex2;
a = b = c = d = f = 0;
classex1 = classex2 = 0;
float classperc, avgex1, avgex2;
student_info( s, SIZE, &classex1, &classex2, &a, &b, &c, &d, &f);
sort(s, SIZE);
avg_exams(classex1, classex2, &avgex1, &avgex2);
print_classinfo(avgex1, avgex2, a, b, c, d, f);
system("PAUSE");
}
Check out your printf() format codes. You can break it into smaller chunks for debugging, to see which portion of the printf() is working unexpectedly.
I don't think the crash is due to your for loops.

I need help regarding the function to show the top 5 scores in text file in C

I am currently creating a really simple program for my beginners course in C programming and I am stuck. I want to be able to print the 5 best scores that are saved in a text file but right now it is only showing the first 5 lines not the best scored lines. The history part works okay and is printing everything but I cannot understand how to print the 5 best scores, maybe it has to do with sorting out the information in the extern text file? Sorry if this post is dumb but I need to ask somewhere (I am really basic at this).
Here is a part of the code that I think is not working properly, it is for codeblocks:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
char name [40]; // Here every integer and character etc. is introduced as global.
int menu(char *name);
int startPractice(int choice);
int startTest(int choice, char *name);
char randomOperator();
int getRandomNumber(int min, int max);
int calc(int a, int b, char c);
int rand(void);
int showHistory();
int saveHistory(char *name, float average);
int showTop5();
struct gamer{
char *username;
float average;
};
int main()
{
printf("Hello and welcome to the program!\n"); // This is the introduction
printf("\nWhat is your name? ");
scanf("%s", &name);
printf("\nWelcome %s! \n\nWhat would you like to do? \n" , name);
menu(&name); // This line calls the main menu.
return 0;
}
int compare(const void *s1, const void *s2)
{
struct gamer *g1 = (struct gamer *)s1;
struct gamer *g2 = (struct gamer *)s2;/* same gender so sort by id */
return g1->average - g2->average;
}
int menu(char *name) { // This is the main menu and whenever this function is called the program starts from here.
int qanswer; // This variable is set so it can be used in this body, it is not a global integer.
printf("\n1. Do practices \n2. Do a test \n3. Quit \n4. Test history \n5. Top 5 \n");
scanf("%d", &qanswer);
switch (qanswer) { // Switch cases for a more compressed code, here only one case will be activated and that is decided by the value of "qanswer".
case 1:
printf("\nNow, you can choose to do practices on: \n\n1. Additions\n2. Subtractions\n3. Addition and Subtractions: ");
printf("\n\nEnter your choice: ");
scanf("%d" , &qanswer);
startPractice(qanswer);
break; //This breaks the code at any chosen case.
case 2:
printf("\nYou will be given 15 questions to solve as the test!\n\n");
printf("\nYou can choose to do the test on: \n\n1. Additions\n2. Subtractions\n3. Addition and Subtractions: ");
printf("\n\nEnter your choice: ");
scanf("%d", &qanswer);
startTest(qanswer, name);
break;
case 3:
printf("\nExiting program... \n");
exit(0); // Shuts down the program.
break;
case 4:
printf("Test history\n");
showHistory();
break;
case 5:
printf("Top 5 test results:\n");
showTop5();
break;
default: // if the user enter anything except 1,2,3 this line of code will be returned.
printf("Your input wasn't valid. Please try again...\n\n");
menu(name); // This calls the main menu again
}
return 0;
}
int startPractice(int choice) { // If practice is chosen then this function will be called.
int a, b, answer1;
char c;
int i;
for (i = 1; i <= 10; i++) { // The for loop runs this code until i=10 and increases by 1 each time. Therefore this code will run 10 times fully.
a = getRandomNumber(1, 30); // This calls the function for a random number.
b = getRandomNumber(1, 30);
if (choice == 1) { // If choice is set to "1" c will be t to + otherwise -.
c = '+';
} else if (choice == 2) {
c = '-';
} else {
c = randomOperator();
}
printf("%d. %d %c %d = ", i, a, c, b);
scanf("%d", &answer1);
while (answer1 != calc(a, b, c)){
printf("Try again! ");
scanf("%d", &answer1);
}
printf("Very good!\n\n");
}
printf("Practice is complete\n");
printf("\nNow what would you like to do?\n");
menu(name);
return 0;
}
int startTest(int choice, char *name) {
int a, b, answer1;
char c;
int counter = 0;
float average;
int i;
for (i = 1; i <= 15; i++) {
a = getRandomNumber(1, 30);
b = getRandomNumber(1, 30);
if (choice == 1) {
c = '+';
} else if (choice == 2) {
c = '-';
} else {
c = randomOperator();
}
printf("%d. %d %c %d = ", i, a, c, b);
scanf("%d", &answer1);
if (answer1 == calc(a, b, c)){
counter++;
}
printf("\n\n");
}
printf("The test is complete\n");
average = (float) counter/(float)15; // This calculates the average score as a float with the counter / 15.
printf("You scored %d out of 15 which is and average of %d %%\n", counter, (int)average*100); // This line takes the value of average and multiply it by 100 to show the percentage.
saveHistory("Test", average);
printf("\nNow what would you like to do?\n");
menu(name); // This function calls the main menu again.
return 0;
}
int calc(int a, int b, char c) { // This function is used to define the equation as (a + b) or (a - b).
switch(c) {
case '+':
return a+b;
case '-':
return a-b;
}
}
char randomOperator() { //This code is used to decide if + or - is going to be used.
switch(getRandomNumber(0,1)) { //Switch statement when you need two or more ways to return a value.
case 0:
return '+'; //If the random number is 0 return is + otherwise it is -.
case 1:
return '-';
}
return '+';
}
int getRandomNumber(int min, int max) { // This simply decides a random value of min 0 and max 1.
return rand() % (max + 1 - min) + min;
}
int showHistory(){
FILE *f;
char c;
f=fopen("test.txt","rt");
if (f) {
while((c=fgetc(f))!=EOF){
printf("%c",c);
}
fclose(f);
printf("\nWhat would you like to do now?\n");
} else {
printf("There is no history file at the moment.");
}
menu(name);
return 0;
}
int saveHistory(char *name, float average){
FILE *f;
char c;
f=fopen("test.txt","a");
fprintf(f, "%s_%.2f\n", name, average);
fclose(f);
return 0;
}
int showTop5(){
//printf("\n");
FILE *f;
char c;
char line[256];
int count = 0;
f=fopen("test.txt","rt");
if (f) {
while (fgets(line, sizeof(line), f)) {
if (strlen(line) > 0) {
count++;
}
}
char delimiter[] = "_";
char *ptr;
fclose(f);
f=fopen("test.txt","rt");
struct gamer gamers[count];
int i = 0;
printf("\n");
while (fgets(line, sizeof(line), f)) {
ptr = strtok(line, delimiter);
char n[40];
strcpy(n, ptr);
//printf("n: %s, ", n);
ptr = strtok(NULL, delimiter);
float avg = *(float *) ptr;
//printf("points: %f\n", avg);
gamers[i].average = avg;
gamers[i].username = n;
i++;
}
qsort(gamers, count, sizeof(struct gamer), compare);
int j;
for(j = 0; j < count; j++){
if (j==5){
break;
}
printf("Rank %d: %s with %.2f %% as average.\n", j+1, gamers[j].username, gamers[j]. average);
}
fclose(f);
} else {
printf("There is no history file at the moment.");
}
menu(name);
return 0;
}
This isnt going to work
ptr = strtok(NULL, delimiter);
float avg = *(float *) ptr;
you are treating the score in the file as though it were the binary representation of a float. It is not, it is text. You need to do
ptr = strtok(NULL, delimiter);
float avg = atof(ptr);
So when i fixed the code that made the program crash (as was mentioned in the answers, thanks!) it seems like the problem with the sorting came from this line of code not treating the values correct, since I wanted to return it as percentage and it must have stopped reading after the decimal which made every user either scoring 0 or 1 if this makes sense. It works now when the return value is multiplied by 100.
Started with this code:
int compare(const void *s1, const void *s2)
{
struct gamer *g1 = (struct gamer *)s1;
struct gamer *g2 = (struct gamer *)s2;/* same gender so sort by id */
return g1->average - g2->average;
}
And this code seems to be the problemsolver.
int compare(const void *s1, const void *s2)
{
struct Gamer *g1 = (struct Gamer *)s1;
struct Gamer *g2 = (struct Gamer *)s2;/* same gender so sort by id */
return (int)((g2->average - g1->average)*100);
After taking into account of previous remarks, it remains other problems before to manage correctly the sort of array of struct gamer by using the qsort() optimized function.
Problem 1 - no allocated space to store the username into a struct gamer.
The struct gamer is using a char *username;;
When reading data from "test.txt" file, the user name is storing only the pointer to the buffer instead of the content gamers[i]->username = n;;
Even if the read username is strcpy(n, ptr);, that storage is in the heap and be overwritten at the next reading operation;
As #pm100 suggestes, the average is decoded as a binary data instead of a text value float avg = *(float *) ptr;
In the showTop5() function use:
while (fgets(line, sizeof(line), f)) {
ptr = strtok(line, delimiter);
char n[40];
strcpy(n, ptr);
ptr = strtok(NULL, delimiter);
float avg = atof(ptr); // #pm100 proposed solution
gamers[i].average = avg;
gamers[i].username = (char *)malloc(sizeof(char)*(strlen(n)+1));
strcpy(gamers[i].username,n); // allocate and copy the username
i++;
}
Instead of
while (fgets(line, sizeof(line), f)) {
ptr = strtok(line, delimiter);
char n[40];
strcpy(n, ptr);
//printf("n: %s, ", n);
ptr = strtok(NULL, delimiter);
float avg = *(float *) ptr;
//printf("points: %f\n", avg);
gamers[i].average = avg;
gamers[i].username = n; // error no size allocated
i++;
}
Problem 2 - When using qsort() the structure of data shall have a fixed-size length. Use an array of pointer struct gamer * to be sorted.
If sizeof(struct gamer) is used to qsort(), the float average and the char *username will be sorted, but it is not optimized;
After allocating the size to store username, it will be not easy to free the memory if the array struct gamer gamers[count]; is allocated from the heap;
It the amount of gamers is large, storing in the heap could be a problem;
Allocating the gamers[] array:
struct gamer **gamers;
int i;
gamers = malloc(count*sizeof(struct gamer *));
for (i = 0; i < count; i++) {
gamers[i] = malloc(sizeof(struct gamer));
}
Manage the reading operation to the array:
See the source code in the Problem 1
Update the compare function of quicksort:
int compare(const void *s1, const void *s2)
{
struct gamer *g1 = *((struct gamer **)s1); // instead of (struct gamer *)s1;
struct gamer *g2 = *((struct gamer **)s2); // instead of (struct gamer *)s2;
// as #BeginnerC suggests, reverse the comparison
return ((int)((g2->average - g1->average)*100));
}
Perform the quicksort:
qsort(gamers, count, sizeof(struct gamer *), compare);
Print the Top 5 gamers:
for(j = 0; j < count; j++){
if (j==5){
break;
}
printf("Rank %d: %s with %.2f %% as average.\n", j+1,
gamers[j]->username, gamers[j]->average);
}
Free the allocated gamers[] array:
for (i = 0; i < count; i++) {
free (gamers[i]->username); // allocated to the username
free (gamers[i]);
}
free(gamers);
Note: in order to simplify the solution of Problem 1 and to have a fixed-size struct gamer, the field char *username could be replaced by char username[40]; (because char n[40]; before strcpy(n, ptr);.

Assigning value to struct variable

I am constructing a adjacency list that I am using to make a directed graph. I read two characters and then make a vertex out of each of them unless a vertex with that char has already been made. I am unfamiliar with structures so this is tripping me up. The values aren't being assigned and I am ending up with an empty list. I am assuming that it is something that has to do with pointers that I am overlooking but I can't seem to find the problem. I hope that someone can help. I will include my code and a sample output.
my.h
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
/* Forward declaration */
struct EDGETAG;
typedef struct
{
char c;
bool isVisited;
struct EDGETAG* p;
} VERTEX;
typedef struct EDGETAG
{
VERTEX* v;
struct EDGETAG* q;
} EDGE;
int main (int argc, char* argv[]);
int adjListSearch (char a, int size, VERTEX* adjList);
adjListSearch.c
#include "my.h"
int adjListSearch (char a, int size, VERTEX* adjList)
{
int i;
if(size == 0)
{
printf("empty\n");
return 1;
}
for(i = 0; i<size; i++)
{
if( adjList[i].c = a)
{
return 0;
printf("found\n");
}
}
printf("notfound\n");
return 1;
}
main.c
#include "my.h"
int main (int argc, char* argv[])
{
int y = 0;
int x = 0;
VERTEX *adjList;
adjList = (VERTEX*)calloc(26, sizeof(VERTEX));
//adjList = malloc(sizeof(VERTEX)*26);
FILE* p;
char *fp;
char a;
char b;
int check1 = 0;
int check2 = 0;
int size = 0;
int searchsuccess = 0;
int i;
//Statements
p = fopen( argv[1], "r");
while(fscanf(p," %c %c", &a, &b)!= EOF)
{
printf("a: %c b: %c\n",a,b);
check1 = adjListSearch(a,size,adjList);
if(check1==1)
{
adjList[size].c = a;
size = size +1;
}
//printf("%c\n", adjList[size].c);
check2 = adjListSearch(b,size,adjList);
if(check2==1)
{
adjList[size].c = b;
size = size +1;
}
}
//End While
printf("Size: %d", size);
for(i=0;i<size;i++)
{
printf("%c\n", adjList[size].c);
}
free(p);
return 0;
}
//End main
Sample Output
a: A b: B
a: B b: C
a: E b: X
a: C b: D
Size: 1
As you can see none of the characters are printed as being inside a structure.
EDIT 1:
I would want the expected output to look like
a: A b: B
a: B b: C
a: E b: X
a: C b: D
Size: 6
A
B
C
E
X
D
Edit 2
Still lost on this if anyone can help.
There were a variety of problems.
You should use fclose(p); and not free(p);.
You should print printf("%c\n", adjList[i].c); instead of printf("%c\n", adjList[size].c);.
As brokenfoot pointed out in his answer, you need to compare a instead of assign it in adjListSearch().
There were multiple unused variables (the compilation options I use complain about them).
There is no need to declare main() (though it doesn't do any harm to the program).
You don't check that there is an argv[1] to use.
You don't check that you opened the file.
You should really use while (fscanf(p, " %c %c", &a, &b) == 2), though it would only matter in this program if there were an odd number of characters to process. At least you were testing fscanf() which is more than many questions we see do.
In the code below, I printed more informative status messages.
main.c
#include "my.h"
int main(int argc, char *argv[])
{
VERTEX *adjList;
adjList = (VERTEX *)calloc(26, sizeof(VERTEX));
FILE *p;
char a;
char b;
int check1 = 0;
int check2 = 0;
int size = 0;
int i;
if (argc != 2)
{
fprintf(stderr, "Usage: %s file\n", argv[0]);
return 1;
}
if ((p = fopen(argv[1], "r")) == 0)
{
fprintf(stderr, "Failed to open file %s for reading\n", argv[1]);
return 1;
}
while (fscanf(p, " %c %c", &a, &b) == 2)
{
printf("a: %c b: %c\n", a, b);
check1 = adjListSearch(a, size, adjList);
if (check1 == 1)
{
printf("Adding a = %c\n", a);
adjList[size++].c = a;
}
check2 = adjListSearch(b, size, adjList);
if (check2 == 1)
{
printf("Adding b = %c\n", b);
adjList[size++].c = b;
}
}
printf("Size: %d\n", size);
for (i = 0; i < size; i++)
{
printf("%c\n", adjList[i].c);
}
fclose(p);
return 0;
}
adjListSearch.c
#include "my.h"
int adjListSearch(char a, int size, VERTEX *adjList)
{
int i;
if (size == 0)
{
printf("empty\n");
return 1;
}
for (i = 0; i < size; i++)
{
if (adjList[i].c == a)
{
printf("found %c\n", a);
return 0;
}
}
printf("not found %c\n", a);
return 1;
}
Data
A B
B C
E X
C D
Sample output
a: A b: B
empty
Adding a = A
not found B
Adding b = B
a: B b: C
found B
not found C
Adding b = C
a: E b: X
not found E
Adding a = E
not found X
Adding b = X
a: C b: D
found C
not found D
Adding b = D
Size: 6
A
B
C
E
X
D
In adjListSearch(), change
if( adjList[i].c = a)
to
if( adjList[i].c == a)

Variance in data in/out of loop

I'm trying to write a program that reads in a .pdb file, which is a file type used in biology applications. This type of file has a standard format with varying white space between data. The file is of the form
ATOM 4 N ALA 1 2.670 1.801 1.072 0.00 0.00
ATOM 5 CA ALA 1 3.225 3.144 1.197 0.00 0.00
ATOM 6 C ALA 1 4.408 3.341 0.256 0.00 0.00
ATOM 7 O ALA 1 4.553 4.394 -0.363 0.00 0.00
.... . .. ... . ..... ..... ..... ..... ....
So my program (probably poorly written) defines a structure, reads in the data (which I stole from another post here http://www.daniweb.com/software-development/c/threads/65455/reading-a-file-using-fscanf#), and stores it into an indexed struct. Now if I print the values inside of the inner if-loop, it spits out the correct data. However, when I print out the same values outside the outer while-loop, it gives me the wrong atom[].name (which just so happens to be HA, the last value in the 3rd column of data in the input file. All other values are correct.
Here is my program
#include <stdio.h>
typedef struct
{
char *atm;
int serial;
char *name;
char *resName;
int resSeq;
double x;
double y;
double z;
double occupancy;
double tempFactor;
} pdb;
int main(int argc, char** argv)
{
int i, j;
pdb atom[28];
char atm[5];
char name[3];
char resName[4];
int serial;
int resSeq;
double x;
double y;
double z;
double occupancy;
double tempFactor;
char buff[BUFSIZ];
FILE *file = fopen("test.pdb", "r");
i = 0;
while (fgets(buff, sizeof buff, file) != NULL)
{
if (sscanf(buff, "%s %d %s %s %d %lf %lf %lf %lf %lf",
atm, &serial, name, resName, &resSeq, &x, &y, &z,
&occupancy, &tempFactor) == 10)
{
atom[i].atm = atm;
atom[i].serial = serial;
atom[i].name = name;
atom[i].resName = resName;
atom[i].resSeq = resSeq;
atom[i].x = x;
atom[i].y = y;
atom[i].z = z;
atom[i].occupancy = occupancy;
atom[i].tempFactor = tempFactor;
i++;
/*printf("%s ", atom[i].atm);
printf("%d ", atom[i].serial);
printf("%s ", atom[i].name);
printf("%s ", atom[i].resName);
printf("%d ", atom[i].resSeq);
printf("%lf ", atom[i].x);
printf("%lf ", atom[i].y);
printf("%lf ", atom[i].z);
printf("%lf ", atom[i].occupancy);
printf("%lf\n", atom[i].tempFactor);*/
}
}
fclose(file);
for (j = 0; j < i; j++)
printf("%d of %d: %s\n", j, i-1, atom[j].name);
return(0);
}
Any idea why this might be happening? In addition, any help on the program format/structure would also be appreciated. I'm more of a Fortran guy, so C structures are out of my realm of expertise.
Thanks in advance.
EDIT: jsn helped me out and Randy Howard refined it. Here is the updated and working program:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
char *atm;
int serial;
char *name;
char *resName;
int resSeq;
double x;
double y;
double z;
double occupancy;
double tempFactor;
} pdb;
int main(int argc, char** argv)
{
int i, j;
pdb atom[28];
int serial;
int resSeq;
double x;
double y;
double z;
double occupancy;
double tempFactor;
char buff[BUFSIZ];
FILE *file = fopen("test.pdb", "r");
i = 0;
while (fgets(buff, sizeof buff, file) != NULL)
{
char *atm = malloc(sizeof(char) * 5);
char *name = malloc(sizeof(char) * 3);
char *resName = malloc(sizeof(char) * 4);
if (sscanf(buff, "%s %d %s %s %d %lf %lf %lf %lf %lf",
atm, &serial, name, resName, &resSeq, &x, &y, &z,
&occupancy, &tempFactor) == 10)
{
atom[i].atm = atm;
atom[i].serial = serial;
atom[i].name = name;
atom[i].resName = resName;
atom[i].resSeq = resSeq;
atom[i].x = x;
atom[i].y = y;
atom[i].z = z;
atom[i].occupancy = occupancy;
atom[i].tempFactor = tempFactor;
i++;
}
}
fclose(file);
for (j = 0; j < i; j++)
{
printf("%s ", atom[j].atm);
printf("%d ", atom[j].serial);
printf("%s ", atom[j].name);
printf("%s ", atom[j].resName);
printf("%d ", atom[j].resSeq);
printf("%lf ", atom[j].x);
printf("%lf ", atom[j].y);
printf("%lf ", atom[j].z);
printf("%lf ", atom[j].occupancy);
printf("%lf\n", atom[j].tempFactor);
}
return(0);
}
Inside the while loop you need to allocate new memory for each char* for each name. You are overwriting them right now.
while (fgets(buff, sizeof buff, file) != NULL)
{
char *atm = malloc(sizeof(char) * 5);
char *name = malloc(sizeof(char) * 3);
char *resName = malloc(sizeof(char) * 4);
if (sscanf(buff, "%s %d %s %s %d %lf %lf %lf %lf %lf",
atm, &serial, name, resName, &resSeq, &x, &y, &z,
&occupancy, &tempFactor) == 10)
You are copying the char array (pointers), so all the names should be the same (the last entry).

Resources