i'm trying to solve this problem but it's not working i think the statement inside 'if' is wrong and i don't know if i can put a pointer inside strcmp like this!!
#include <string.h>
#include <studio.h>
struct PersonCar {
char pname[20];
char cModel[20];
float price;
};
struct PersonCar pc[4];
float calculatePrice(struct PersonCar *p, char *name) {
p = malloc(sizeof(pc));
float s = 0;
for (int i = 0; i < 4; i++) {
if ((strcmp((p[i].pname), name)) == 0) //(p+i)->pname
s += (p + i)->price; //(p+i)->price; }
return s;
}
int main() {
// entering the element of the array from the user
char A[20];
printf("Enter a name : ");
fgets(A, sizeof(A), stdin);
printf("the total price of the registered cars for %s =%f\n", A,
calculatePrice(&pc, A));
}
First you need some data (I have included some statically initialized data in my version)
Second, you need to eliminate the malloc() statement at the beginning of the function, that modifies the passed pointer to the data and makes it to point to an uninitialized data, that is very unprobable that finds any register that matches.
You h ad better to know the size of the data array, and pass the number of entries on it.
You need to eliminate the last '\n' from the array read by fgets(). If you don't, it is comparing "smith" against "smith\n", which will never be equal. I suggest one way below, but you have to be careful and read the man page of strtok, as it modifies the source string, this can be not what you want (while in this case is preciselly what we want)
To illustrate, I have written this sample code (but a full program you can compile and execute) to see the logic.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct PersonCar {
char *pname;
char *cModel;
float price;
};
/* initialized data */
struct PersonCar pc[] = {
{ .pname = "smith",
.cModel = "foo",
.price = 10.50F,
}, {
.pname = "montgomery",
.cModel = "bar",
.price = 20.50F,
}, {
.pname = "mckormack",
.cModel = "blah",
.price = 35.50F,
}, {
.pname = "smith",
.cModel = "pong",
.price = 55.50F,
}, {
.pname = "phelps",
.cModel = "ping",
.price = 75.50F,
},
};
size_t pc_count = sizeof pc / sizeof pc[0];
float calculatePrice(
struct PersonCar *p,
size_t p_count,
char *name)
{
float total = 0.0;
for (int i = 0; i < p_count; i++) {
if (strcmp(p[i].pname, name) == 0)
total += p[i].price; /* found */
}
/* not found */
return total;
}
int main()
{
// entering the element of the array from the user
char A[80];
printf("Enter a name : ");
fgets(A, sizeof(A), stdin);
char *p = strtok(A, "\n"); /* chop the last \n if present */
printf("the total price of the registered cars for %s =%f\n",
p, calculatePrice(pc, pc_count, p));
}
I think you're looking for something like:
#include <string.h>
#include <stdio.h>
struct PersonCar {
char pname[20];
char cModel[20];
float price;
};
struct PersonCar pc[4] = {
{"abc", "", 1.0},
{"def", "", 2.0},
{"abc", "", 3.0},
{"jkl", "", 4.0},
};
float
calculatePrice(struct PersonCar *p, char *name)
{
float s = 0;
for( struct PersonCar *e = p + 4; p < e; p++ ){
if( strcmp((p->pname), name) == 0 ){
s += p->price;
}
}
return s;
}
int
main(void)
{
char A[20];
printf("Enter a name : ");
fgets(A, sizeof(A), stdin);
printf("the total price of the registered cars for %s =%f\n", A,
calculatePrice(pc, A));
}
One glaring issue here is that you're not dealing with the newline in the input, but since I don't know how you're actually initializing the data it's not clear how you want to deal with it.
Related
I'm trying to create an array of Product structs and then print the name and code of each Product in the array, but I keep getting a segmentation fault. I have tried to insert each value without a loop and then printing, and it works, but I'd like to automate it. The function fill_products fills the products array according to the user's input, and the select_products prints each name-code pair for the entire array.
This is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int code;
char *name;
float price;
} Product;
void select_products(Product *products, int len)
{
int i;
printf("%-30s%s\n", "Name", "Code");
for (i = 0; i < len; i++)
{
printf("%-30s%d\n", products[i].name, products[i].code);
}
return;
}
void fill_products(Product *products, int len)
{
int i, code;
char *name;
float price;
for (i = 0; i < len; i++)
{
printf("Insert product name (%d / %d): ", i + 1, len);
scanf("%s", &name);
printf("Insert product price (%d / %d): ", i + 1, len);
scanf("%f", &price);
products[i].code = i;
products[i].name = name;
products[i].price = price;
}
return;
}
int is_alloc(Product *products)
{
if (products == NULL)
{
printf("Error: memory allocation unsuccessful.\n");
}
return products != NULL;
}
int main(void)
{
int len, n_bytes;
Product *products;
printf("Insert length of array: ");
scanf("%d", &len);
n_bytes = sizeof *products * len;
products = malloc(n_bytes);
if(!is_alloc(products))
{
exit(0);
}
fill_products(products, len);
select_products(products, len);
free(products);
return 0;
}
I keep getting a segmentation fault.
Please enable compiler warnings, and pay attention to them.
This code:
char *name;
...
scanf("%s", &name);
is bogus and doesn't do at all what you intend.
You must either allocate space for name separately (and then not forget to free() it), or make that space available in the Product structure like so:
typedef struct
{
int code;
char name[100];
float price;
} Product;
(this assumes there is a reasonable limit on name length).
I am trying to free the memory allocated by my getSongInfo function, I have tried using a pointer to the function call but I get an error "cannt assign int to type int*" error. Any help would be great as the current way I have seems like it may work, but I might be completely wrong. Thanks!
Original Attempt:
int *memPtr = NULL
memPtr = getSongInfo(&fillPtr[arrayCounter], tempArtist[counter], tempSong[counter]);
Gives error!
Current Attempt:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996)
int getSongInfo(struct songInfo *pFillInfo, char *artistName, char *songName);
void printSongInfo(struct songInfo songList[10]);
struct songInfo {
char *songArtist;
char *songTitle;
};
int main(void)
{
struct songInfo *fillPtr;
struct songInfo songList[10];
fillPtr = &songList[0];
char tempArtist[10][30];
char tempSong[10][30];
int *memPtr = NULL;
int i = 0;
int counter = 0;
int arrayCounter = 0;
while (counter != 10)
{
printf("Please enter the artist name: ");
fgets(tempArtist[counter], sizeof(tempArtist[counter]), stdin);
tempArtist[counter][strcspn(tempArtist[counter], "\n")] = 0;
printf("Please enter the song name: ");
fgets(tempSong[counter], sizeof(tempSong[counter]), stdin);
tempSong[counter][strcspn(tempSong[counter], "\n")] = 0;
getSongInfo(&fillPtr[arrayCounter], tempArtist[counter], tempSong[counter]);
printf("Song and Artist Captured! \n");
counter++;
arrayCounter++;
}
printSongInfo(fillPtr);
free(fillPtr->songArtist);
free(fillPtr->songTitle);
}
int getSongInfo(struct songInfo *pFillInfo, char *artistName, char *songName)
{
pFillInfo->songArtist = (char*)malloc(strlen(artistName) + 1);
pFillInfo->songTitle = (char*)malloc(strlen(songName) + 1);
strcpy(pFillInfo->songArtist, artistName);
strcpy(pFillInfo->songTitle, songName);
return 1;
}
void printSongInfo(struct songInfo songList[10])
{
int counter = 0;
while (counter != 10)
{
printf("%-35s %-35s\n", songList[counter].songArtist, songList[counter].songTitle);
counter++;
}
}
Your getSongInfo function does not return a pointer, so attempting to put the return value into a variable and then free it is pointless. The pointers in question are inside the struct songInfo, specifically, the fillPtr variable (which is actually redundant, since songList and fillPtr point to the same location).
In addition, please be aware that strcspn will not always return a valid index. If it does not find a match, it will return the length of the first argument.
I think this is more like what you are trying to do:
int main(void)
{
const int numSongs = 10;
struct songInfo songList[numSongs];
char tempArtist[30];
char tempSong[30];
int i;
int newline_idx;
for (i = 0; i < numSongs; ++i)
{
printf("Please enter the artist name: ");
fgets(tempArtist, sizeof(tempArtist), stdin);
newline_idx = strcspn(tempArtist, "\n");
if (newline_idx < sizeof(tempArtist))
tempArtist[newline_idx] = 0;
printf("Please enter the song name: ");
fgets(tempSong, sizeof(tempSong), stdin);
newline_idx = strcspn(tempSong, "\n");
if (newline_idx < sizeof(tempSong))
tempSong[newline_idx] = 0;
getSongInfo(&songList[i], tempArtist, tempSong);
printf("Song and Artist Captured! \n");
}
for (i = 0; i < numSongs; ++i)
{
free(songList[i].songArtist);
free(songList[i].songTitle);
}
}
You might consider separating the code for free()ing each struct into its own function.
You might also consider heeding that compiler warning instead of ignoring it, as Bodo commented. Careless handling of strings from stdin is dangerous.
i wrote some code that is supposed to find the location of a given string in an array of strings.
problem is- it doesn't give the location. it gives something else.
i understand that probably the problem has to do with the differences between the pointers that are involved- a previous version that dealt with finding the position of a letter in a word worked well.
after a lot of attempts to figure out where is the bug, i ask your help.
kindly, explain me what should be done.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int what (char * token);
main()
{
int i=0;
char string[]="jsr";
char *token;
token=&string[0];
i=what(token);
printf(" location of input is %d \n", i);
return 0;
}
int what (char * token)
{
int i=1;
char *typtbl[]={"mov",
"cmp",
"add",
"sub",
"not",
"clr",
"lea",
};
char * ptr;
ptr=(char *)typtbl;
while (!(strcmp(ptr,token)==0))
{
ptr=(char *)(typtbl+i);
i++;
}
return i;
}
As pointed out, you did not design function what properly. What value should it return if your search function go through all the pointers but does not find the desired string? Typically in that case return -1 would be a choice to indicate nothing found. Also in this case, using a for loop would probably be more suitable, you can just return the index immediately instead of going through all pointers.
int what(char *token)
{
char *typtbl[] = {
"mov",
"cmp",
"add",
"sub",
"not",
"clr",
"lea",
};
for( size_t i = 0; i < sizeof(typtbl)/sizeof(char*); ++i )
{
char *ptr = typtbl[i];
if(strcmp(ptr, token) == 0)
{
return i; // found something
}
}
return -1; // found nothing
}
A cleaner working version.
Main issue is in the (char *)(typtbl+i) replaced by typtbl[i] in the following code. typtbl+i is equivalent to &typtbl[i], so if my memory is good, it's a pointer on the pointer of the string and not the pointer of string itself
I added a NULL at the end of the array to be able to stop if the string is not present and return -1 to clearly say it was not found.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int what(char *token);
int main()
{
int i = 0;
char string[] = "jsr";
i = what(string);
printf(" location of input is %d \n", i);
return 0;
}
int what(char *token)
{
char *typtbl[] = {
"mov",
"cmp",
"add",
"jsr",
"not",
"clr",
"lea",
NULL
};
int i = 0;
while(typtbl[i] && !(strcmp(typtbl[i], token) == 0)) {
++i;
}
if(!typtbl[i])
i = -1;
return i;
}
char *token; token=&string[0]; was useless because string == &string[0].
A few things:
Your main function is missing its return type.
The while loop in what doesn't stop when the element isn't found. Therefore you are reading out of bounds.
This should do the work w/o pointer arithmetic.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int what (char * token);
int main(){
int i=0;
char string[]="jsr";
char *token;
token=&string[0];
i=what(token);
printf(" location of input is %d \n", i);
return 0;
}
int what (char * token){
unsigned int i=0;
char *typtbl[]={"mov",
"cmp",
"add",
"sub",
"not",
"clr",
"lea",
};
unsigned int typtbl_x_size = sizeof(typtbl)/sizeof(typtbl[0]);
char * ptr;
ptr=typtbl[i];
while (!(strcmp(ptr,token)==0)){
i += 1;
if (i >= typtbl_x_size){
printf("element not in list\n");
return -1;
}
ptr=typtbl[i];
}
return i;
}
Recently, I took a subject called Data structure. I've created a program to try out my knowledge but don't know why the program did not work. I can't figure it out so I post it here to ask for solution. I hope people can help me. I am newbie here. So please ignore my opinion if my opinion is found annoying.
#include <stdio.h>
int main()
{
struct Book
{
char title[50];
int year;
float price;
};
int i;
struct Book books[50];
books[0].title="Bullshit";
books[0].year=132;
books[0].price=146.9;
books[1]=(struct Book){"Money",1344,189.4
};
for(i=0;i<2;i++)
{
printf("Book Title is : %s\n",books[i].title);
printf("Book Year is %d\n",books[i].year);
printf("Book price is %3.2f\n",books[i].price);
printf("\n\n");
}
}
1 I would make declaration of struct rather outside main than inside
2 Try changing char title[50] to char *title
#include <stdio.h>
struct Book {
char *title;
int year;
float price;
};
int main() {
int i;
struct Book books[50];
books[0].title = "Bullshit";
books[0].year = 132;
books[0].price = 146.9;
books[1] = (struct Book) {"Money", 1344, 189.4
};
for (i = 0; i < 2; i++) {
printf("Book Title is : %s\n", books[i].title);
printf("Book Year is %d\n", books[i].year);
printf("Book price is %3.2f\n", books[i].price);
printf("\n\n");
}
}
Why it didn't worked before?
In c arrays are not assignable by = operator.
You could do something like instead title[0] = 'B'; title[1] = 'u', etc....(or use strcpy which does it for you).
char *x is not really an array, it's just pointer to single char.
If we write x = "abc", we are telling the compiler: set x to 'a', next byte to 'b', next to 'c', and next to 0(not '0', just zero).
And when you do printf("%s",x), the printf function prints chars from the place in memory specified by x until it see 0 byte.
char *x = "abcd";
char *y = x;
while(*y != 0){ // this loop acts like printf("%s",x);
printf("%c",*y);
y++;
}
See also this and this question.
Or if you are using c++, not c, use std::string:
#include <cstdio>
#include <string>
struct Book {
std::string title;
int year;
float price;
Book(std::string t, int y, float p) {
title = t;
year = y;
price = p;
}
};
int main() {
int i;
Book books[50];
books[0].title = "Bullshit";
books[0].year = 132;
books[0].price = 146.9;
books[1] = Book(std::string("Money"), 1344, 189.4);
for (i = 0; i < 2; i++) {
printf("Book Title is : %s\n", books[i].title.c_str());
printf("Book Year is %d\n", books[i].year);
printf("Book price is %3.2f\n", books[i].price);
printf("\n\n");
}
}
this
books[0].title="Bullshit";
is not valid. title is defined as char[50]. Either do
strcpy(books[0].title, "BS");
This will copy the bytes of BS to title. Or do
struct Book
{
char *title;
int year;
float price;
};
...
books[0].title = strdup("BS");
This sets title up as a pointer to a char string. strdup will allocate space for the string and copy BS to that space. You will have to free that allocated space.
Or - the best. Use std::string
struct Book
{
std::string title;
int year;
float price;
};
....
books[0].title = "BS";
And as a final thought - life goes better with std::vector instead of raw arrays
Okay, so we're supposed to prompt a user to enter 25000 lines of text.
Each line contains three integers each. We are then to pass the third integer in that line to another struct, and connect each integer until you have 25000 interconnected integers.
Here's what I've tried:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct graph{
int begin;
int end;
int cost;
} PathEdge;
int comp_fcn(const void *a, const void *b) {
return ((PathEdge *) a)->cost - ((PathEdge *) b)->cost;
}
int main(void)
{
int nlines,i;
char r;
int ecost,ebegin,eend;
scanf("%d",&nlines);
PathEdge edges[nlines+1];
for(i=0;i<nlines;i++)
{
scanf("%d, %d, %dn",&ebegin, &eend, &ecost);
edges[i].begin = ebegin;
edges[i].end = eend;
edges[i].cost = ecost;
struct town
{
struct town *north;
int name[25000];
};
struct town *root, *current;
root = malloc(sizeof(struct town));
root->north = NULL;
strcpy (root->name,ecost);
current = malloc(sizeof(struct town));
current->north = root;
strcpy (current->name,ecost);
}
printf("Please enter a node that you want to examine. If you want to exit, please press 'X'.n");
scanf("%c",&r);
switch(r)
{
case 'X':
case 'x':
printf("You entered a wrong value. Gomen. Try againn.");
break;
default:
if((0<r)&&(r<25000))
{
printf("You have accessed node %dn",r);
printf("Its neighboring nodes are %dn",edges[r].cost);
printf("Its neighboring nodes are %dn",edges[i].cost);
}
else
{
printf("Invalid input again. Please do try again. Thanksn");
}
break;
}
return 0;
}
And there are warnings...
"passing argument 1 of strcpy from incompatible pointer type"
"passing argument 2 of strcpy makes pointer from integer without a cast"
expected char*__ restrict __ but argument is of type 'int'
plus when I inputted that 25000 lines of text, segmentation fault happens. Please help. Thank you!
strcpy is for copying strings (i.e. zero terminated byte char "arrays"), you maybe should use memcpy instead.
Or if you just want to assign a single integer to one element in the array, use plain assignment:
current->name[someIndex] = ecost;
Or, maybe you intend that thename member should be a string? Then you should be using an array of characters and not integers. And you need to convert integer values to strings, using e.g. sprintf:
sprintf(current->name, "%d", ecost);
you can convert the integer to string using itoa and copy the string into root->name.
char str[20];
itoa(ecost, str, 10);
strcpy(root->name, str);
You did not state your exact issue so I am assuming you are overwhelmed and in that case you should try partitioning your implementation into functions so that you can work on isolated problems instead of a web of interconnected problems.
Here is one example:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct graph {
int begin;
int end;
int cost;
} PathEdge;
const char * GenerateInput()
{
static char local[2000];
static int last = 0;
int a, b, c;
a = last++;
b = last++;
c = last++;
sprintf_s(local, 2000, "%i %i %i", a, b, c);
return local;
}
void PathEdgeInitializeFromString(PathEdge * edge, const char * str)
{
sscanf_s(str, "%d %d %dn", &edge->begin, &edge->cost, &edge->end);
}
void QueryAndPrint(PathEdge * edges, int edges_n)
{
printf("Enter a number from 1 to %i: ", edges_n);
int index = 0;
scanf_s("%i", &index);
--index;
if (index < 0 || !(index < (edges_n)))
printf("Error");
else
printf("%i, %i, %i\n", edges[index].begin, edges[index].cost, edges[index].end);
}
int main() {
PathEdge edges[25000];
for (int i = 0; i < 25000; ++i)
{
const char * line = GenerateInput();
PathEdgeInitializeFromString(edges + i, line);
}
QueryAndPrint(edges, 25000);
return 0;
}