Problems with editing and showing customer data - c - c

I'm doing a customer and product management project in C. And right now I'm having some problems:
in the part of showing the customer's data, he doesn't show the whole name, only the first letter; the phone number puts a number that I didn't enter; in nif does not say what corresponds; as well as the email that put characters that I did not indicate.
Already in the edit part, it edits but not correctly, because it changes data that I didn't ask for and others I don't sample.
Stays like this:
-- customer creation:
enter image description here
-- show customer data:
enter image description here
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define BUFFER 64
/* List structure declared to store our data. */
typedef struct list {
int *customer_code;
char name;
int age;
int tin;
char email;
double phone;
char country;
struct list *next;
} Data;
/* Prototype of data handling functions. */
int *data_start(int *customer_code, char name, int age, int tin, char email, double phone, char country);
int *insert_data(Data *data, int *customer_code, char name, int age, int tin, char email, double phone, char country);
int *edita_dados(Dados *dados, int item, int *customer_code, char name, int age, int tin, char email, double phone, char country);
void display_data(Data *data);
void data_search(Data *data, char *key);
int *delete_data(Data *data);
int check_empty(Data *data);
/* Prototype of menu functions.*/
void insert(void);
void edit(void);
void displays(void);
void search(void);
void delete(void);
/* Initializes the main data structure. */
int *main = NULL;
/* Cria a nova lista apontando o proximo no para NULL. */
int *data_start(int *cliente_codigo, char name, int age, int tin, char email, double phone, char country) {
Data *new;
new = (Data *) malloc(sizeof (Data));
new->customer_code = (int *) malloc(strlen(customer_code) + 1);
strncpy(new->customer_code, customer_code, strlen(customer_code) + 1);
new->name = name;
new->age = age;
new->tin = tin;
new->email = email;
new->phone = phone;
new->country = country
new->next = NULL;
return new;
}
/* As the list is no longer empty, we point the next node to the previous list. */
int *insert_data(Data *data, int *customer_code, char name, int age, int tin, char email, double phone, char country) {
Data *new;
new = (Data *) malloc(sizeof (Data));
new->customer_code = (int *) malloc(strlen(customer_code) + 1);
strncpy(new->customer_code, customer_code, strlen(customer_code) + 1);
new->name = name;
new->age = age;
new->tin = tin;
new->email = email;
new->phone = phone;
new->country = country
new->next = Data;
return new;
}
/* Cycles through all fields in the list and prints until the next pointer reaches NULL. */
int *edita_dados(Data *data, int item, int *customer_code, char name, int age, int tin, char email, double phone, char country) {
int i = 0;
/*while(data != NULL && i <= item) {
data = data->next;
}*/
while (data->next != NULL && i < item) {
data = data->next;
++i;
}
if (data != NULL && i == item) {
strcpy(data->customer_code, customer_code);
new->name = name;
data->age = age;
data->tin = tin;
data->email = email;
data->phone = phone;
data->country = country
}
printf("Successfully edited.\n");
}
/* Cycles through all fields in the list and prints until the next pointer reaches NULL. */
void display_data(Data *data) {
printf("Registration Report\n\n");
printf("------------------------\n");
for (; data != NULL; data = data->next) {
printf("Name: %c\n", data->name);
printf("Age: %d\n", data->age);
printf("TIN: %d\n", data->tin);
printf("Email: %c\n", data->email);
printf("Phone: %lf\n", data->phone);
printf("Country: %c\n", data->country);
printf("------------------------\n");
}
}
/* Cycle through each end comparing the name to the key. */
void data_search(Data *data, char *key) {
int find = 0;
printf("registration data\n\n");
for (; data != NULL; data = data->next) {
if (strcmp(key, data->customer_code) == 0) {
printf("------------------------\n");
printf("Name: %c\n", data->name);
printf("Age: %d\n", data->age);
printf("TIN: %d\n", data->tin);
printf("Email: %c\n", data->email);
printf("Phone: %lf\n", data->phone);
printf("Country: %c\n", data->country);
printf("------------------------\n");
find++;
}
}
if (find == 0)
printf("No results found.\n\nPress a key to continue.\n\n");
else
printf("%d records were found.\n\nPress a key to continue.\n\n", find);
}
/* Deletes the last record entered. */
int *delete_data(Data *data) {
Data *new;
new = data->next;
free(data->customer_code);
free(data);
printf("The last record entered was deleted successfully!\n");
return new;
}
/* it's worth checking whether the list is NULL or not. */
int check_empty(Data *data) {
if (data == NULL) {
printf("List empty!\n");
return 1;
} else
return 0;
}
/* Gets the necessary data to call the data handling functions. */
void insert(void) {
int intend_tin;
Data d;
d.customer_code = (char *) malloc(BUFFER);
printf("Client Code: ");
scanf("%d", d.customer_code);
printf("Type your name: ");
scanf("%s", &d.name);
printf("\nEnter your age:");
scanf("%d", &d.age);
printf("\nEnter your email:");
scanf("%s", &d.email);
printf("\nEnter your mobile number: ");
scanf("%lf", &d.phone);
printf("TIN present? ");
scanf("%s", &intend_tin);
if (intend_tin == 's' || intend_tin == 'S') {
while (1) {
printf("\n\tEnter your TIN: ");
scanf("%d", &d.tin);
if (&d.tin >= 999999999) {
printf("\tNumber with more than 9 digits is not allowed. "
"Please try again.");
} else if (&d.tin <= 99999999) {
printf("\tNumber with less than 9 digits is not allowed. "
"Please try again.");
} else
break;
}
printf("\tValid.\n");
} else {
printf("TIN not entered\n");
}
printf("What is your country? ");
scanf("%s", &d.country);
if (main == NULL)
main = data_start(d.customer_code, d.name, d.age, d.email, d.phone, d.tin, d.country);
else
main = insert_data(main, d.customer_code, d.name, d.age, d.email, d.phone, d.tin, d.country);
}
/* Gets the necessary data to call the data handling functions. */
void edit(void) {
int item = 0;
Data d;
d.customer_code = (char *) malloc(BUFFER);
printf("Enter the customer code you want to change the data:");
scanf("%d", d.customer_code);
printf("Enter the item to edit:\n--> ");
scanf("%d", &item);
printf("\Enter your email:");
scanf("%s", &d.email);
printf("\nEnter your mobile number: ");
scanf("%lf", &d.phone);
if (main == NULL)
main = data_start(d.customer_code, d.name, d.age, d.email, d.phone, d.tin, d.country);
else
edit_data(main, item, d.customer_code, d.name, d.age, d.email, d.phone, d.tin, d.country);
}
void displays(void) {
if (!check_empty(main))
display_data(main);
}
void search(void) {
Data d;
if (!check_empty(main)) {
d.customer_code = (char *) malloc(BUFFER);
printf("Enter the name to search:\n--> ");
scanf("%d", d.customer_code);
data_search(main, d.customer_code);
}
}
void delete(void) {
if (!check_empty(main))
main = delete_data(main);
}

In the struct definition, nome is of type char. So scanf("%s", &d.nome); is (almost certainly) undefined behavior. nome is large enough to store a string of length zero (it can only hold the null terminator), and if there is any data for scanf to write, then the behavior is undefined since you've overflowed the buffer. If you want to store a string, you need to give it some space. Perhaps just do:
struct lista {
int *cliente_codigo;
char nome[256]; /* Make nome a character array */
int idade;
int nif;
char email;
double phone;
char pais;
struct lista *proximo;
};
and then read into it with "%255s" to ensure you don't overflow the buffer. Also, check the value returned by all your scanf and handle invalid data. (eg, discard bad input, or throw an error).
There may be other issues in your code as well, but this is certainly a show stopper.

Related

Why does printing from this struct give a segmentation fault?

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).

Searching for a string in an array without strcmp

I have a struct in this form:
typedef struct student{
double student_no;
char name[50];
char surname[50];
double phone_no;
char mail[50];
};
struct student person[100];
printf("Student's mail address: ");
scanf("%s", person[i].mail); //i use codeblocks and it works without the sign &
First I create an array of mails. Then I get a mail for user, then check if it is in my array that I created in the first place. I have to do it without strcmp(), and that's where I get stuck. Here is what I've tried so far:
char *e1, *e2;
int comp;
typedef struct info{
char email[50];
};
struct info mailaddress[0];
printf("Enter the mail address to search: ");
scanf("%s", mailaddress[0]);
for (int i = 0; i < u; i++) {
for (int j = i + 1; j < u; j++) {
e1 = person[i].mail;
e2 = mailaddress[j].email;
comp = 0;
while (*e1 && *e2) {
if (*e1 != *e2) {
comp = *e1 - *e2;
break;
}
++e1;
++e2;
}
if (comp == 0)
printf("%s\t %s %15.lf %15.lf %s\n",
person[i].name,
person[i].surname,
person[i].student_no,
person[i].phone_no,
person[i].mail);
}
}
Try like this
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <conio.h>
#include <string.h>
#define NO_MAX 20
#define NAME_MAX 20
#define SURNAME_MAX 20
#define PHONE_NO_MAX 20
#define MAIL_NO_MAX 50
struct student{
char student_no[NO_MAX + 1];
char name[NAME_MAX + 1];
char surname[SURNAME_MAX + 1];
char phone_no[PHONE_NO_MAX + 1];
char mail[MAIL_NO_MAX + 1];
struct student *ptr_next;
};
struct student *ptr_head = NULL;
struct student *ptr_position;
void enter_item(char *ptr_label, char *ptr_result, int max){
// enter item until pressed enter to finished
char tmp[256];
do {
printf("%s: ", ptr_label);
gets(tmp);
} while((strlen(tmp) > max));
strcpy(ptr_result, tmp);
}
void enter_list(void) {
char more;
struct student *ptr_new;
do{
// order dynamic memory
ptr_new = (struct student *) malloc(sizeof(struct student));
if(ptr_new) {
// enter item
enter_item("student_no", ptr_new->student_no, NO_MAX);
enter_item("name", ptr_new->name, NAME_MAX);
enter_item("surename", ptr_new->surname, SURNAME_MAX);
enter_item("phone_no", ptr_new->phone_no, PHONE_NO_MAX);
enter_item("mail", ptr_new->mail, MAIL_NO_MAX);
// next item
ptr_new-> ptr_next = ptr_head;
ptr_head = ptr_new;
// enter item again or not
printf("- again(Y/N)? -");
do{
more = toupper(getch());
} while(!(more=='Y' || more=='N'));
printf(" %c\n\n", more);
}
else {
printf("Memory isn't enough!\n");
break;
}
} while(more == 'Y');
}
void search_mail() {
// enter mail
struct student *ptr_search;
ptr_search = (struct student *) malloc(sizeof(struct student));
enter_item("mail searching", ptr_search->mail, MAIL_NO_MAX);
char *mail = ptr_search->mail;
// searching mail
ptr_position = ptr_head;
while(ptr_position) {
if(strcmp(mail, ptr_position->mail) != 0) {
ptr_position = ptr_position-> ptr_next;
}
else {
printf("Email is found\n");
return;
}
}
printf("Email isn't found!\n");
}
int main()
{
enter_list();
search_mail();
return 0;
}
Result:
bool streq(char *a, char *b)
{
while (*a && *b && *a != *b)
a++, b++;
return !*a && !*b;
}

malloc array of struct inside of struct

I have project in school where in need to make a struct of AirportManager which holds the amount of airports and an array of Airport (another struct). I started writing the code but I having trouble with the malloc of the array of airports.
I attahced to code I write so far, the problem I have is that the values dont saved in the airportArray in the AirportManager.
//AirportManger Struct
typedef struct {
Airport* airportArray;
int airportAmount;
}AirportManager;
void initAirportManager(AirportManager* airportManager)
{
airportManager->airportAmount = 0;
airportManager->airportArray = (AirportManager*)malloc(0);
}
void addAirport(AirportManager* airportManager)
{
Airport airport;
printf("Enter Airport Name: ");
scanf("%s", airport.airportName);
printf("Enter Airport Address: ");
scanf("%s", airport.airportAddress);
airportManager->airportAmount++;
airportManager->airportArray = (Airport*)realloc(airportManager->airportArray, airportManager->airportAmount * sizeof(Airport));
airportManager->airportArray = airport;
}
//Airport Struct
typedef struct {
char airportName[MAX];
char airportAddress[MAX];
}Airport;
//Main
AirportManager airportManager;
initAirportManager(airportManager);
addAirport(&airportManager);
The code has some issues. We shouln't:
allocate zero bytes with malloc(0)
assign twice to airportManager->airportArray
use scanf
Here is the code modified. It uses malloc and realloc better, and fgets instead of scanf.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZ 512
typedef struct {
char airportName[SIZ];
char airportAddress[SIZ];
} Airport;
typedef struct {
Airport* airportArray;
int airportAmount;
} AirportManager;
// Call first on AirportManager
void initAirportManager(AirportManager* airportManager)
{
airportManager->airportAmount = 0;
airportManager->airportArray = NULL;
}
// Call last on AirportManager
void finalAirportManager(AirportManager* airportManager)
{
airportManager->airportAmount = 0;
if (airportManager->airportArray != NULL)
free(airportManager->airportArray);
airportManager->airportArray == NULL;
}
// Add an airport to the manager
void addAirportByNameAndAddress(AirportManager* airportManager, char *name, char *address)
{
// Calculate the amount of memory needed
size_t mem = (airportManager->airportAmount + 1) * sizeof(Airport);
// Get the memory required
Airport* newAirports = NULL;
if (airportManager->airportArray == NULL)
newAirports = (Airport*)malloc(mem);
else
newAirports = (Airport*)realloc(airportManager->airportArray, mem);
if (newAirports == NULL)
{
// error: out of memory
return;
}
// Copy the name and the address to new the new Airport
Airport *current = newAirports + airportManager->airportAmount;
memset(current->airportName, '\0', SIZ);
strncpy(current->airportName, name, SIZ - 1);
memset(current->airportAddress, '\0', SIZ);
strncpy(current->airportAddress, address, SIZ - 1);
// Update the manager
airportManager->airportAmount++;
airportManager->airportArray = newAirports;
}
void addAirport(AirportManager* airportManager)
{
char name[SIZ] = { 0 };
char address[SIZ] = { 0 };
printf("Enter Airport Name: ");
fgets(name, SIZ - 1, stdin);
printf("Enter Airport Address: ");
fgets(address, SIZ - 1, stdin);
addAirportByNameAndAddress(airportManager, name, address);
}
void main() {
AirportManager airportManager;
initAirportManager(&airportManager);
addAirport(&airportManager);
finalAirportManager(&airportManager);
}

Trouble with a pointer not being initialized

I'm trying to make a program that asks for a users name and the amount of money they owe to the company. The problem is, every time I try to compile the program I get this warning saying that "user may not be initialized." I'm not quite sure what that means. Any help to out what I'm doing wrong? Thanks!
#define END '\0'
#define LENGTH 20
struct info
{
char lastName[LENGTH];
float payment;
};
int customerS();
void accounts(struct info *userStart, int amount);
void changeNames(struct info *userStart, int amount);
void sort(struct info *userStart, int amount);
void results(struct info *userStart, int amount);
int main()
{
struct info *user;
int amount;
while((amount = customers()) != 0)
{
accounts(user, amount);
changeNames(user, amount);
sortNames(user, amount);
results(user, amount);
free(user);
}
return 0;
}
int customers()
{
int choice;
do
{
printf("\nHow many customers do you have (2 to 300, 0=quit): ",
scanf("%d", &choice);
}
while((choice < 2|| choice > 300) && choice != 0);
return choice;
}
void accounts(struct info *userStart, int amount)
{
struct info *user;
char *name[LENGTH];
float owed;
for(user = userStart; (user - userStart) < amount; user++)
{
scanf (" %s", name[LENGTH]);
getchar();
do
{
name[LENGTH] = getchar();
name[LENGTH]++;
}
while(!('\n'));
user->lastName[LENGTH + 1] = END;
scanf("%f", &owed);
user->payment = owed;
}
return;
}
void changeNames(struct info *userStart, int amount)
{
char *fast = &userStart->lastName[LENGTH],
*slow = &userStart->lastName[LENGTH];
if(tolower(*fast))
*slow++ = toupper(*fast);
while(*fast != END)
{
if(!isspace(*fast) || isalpha(*fast))
*slow++ = tolower(*fast);
fast++;
}
*slow = END;
return;
}
void sort(struct info *userStart, int amount)
{
struct info *user;
char *in,
*out,
temp;
for(out = user->lastName; (out - userStart->lastName) < amount; out++)
{
for(in = out + 1; (in - userStart->lastName) < amount; in++)
{
if(strcmp(user->lastName, userStart->lastName))
{
temp = *out;
*out = *in;
*in = temp;
}
}
}
return;
}
void results(struct info *userStart, int amount)
{
struct info *user;
printf("\nName: %s Payment: $%.2f", user->lastName, user->payment);
return;
}
struct info *user;
This allocates a pointer to a user struct, not the struct itself.
So, you can allocate it on the stack via struct info user; and pass &user to the functions, or dynamically allocated it via user = (struct info*)malloc( sizeof(struct info) ).
Either way should avoid your segmentation fault (because the pointer is not initialized).
..)

writing to strings inside a structure doubly linked list in C

I have an issue with my code, I changed a few of the functions to accomodate the structure I added, so instead of having variables all over the place, but now it does not work at all. I need it to create a structure person, then it prompts the user to enter the persons name, and age; then it asks for more persons to fill a doubly linked list which stops the loop if nothing is input for the persons name. THEN it spits out the reverse of what I input into the doubly linked list. All help is appreciated ^-^
struct person
{
char name[10][41];
int age[10];
};
int write(struct person *people);
void print(struct person *people);
int main(void)
{
char names[10][41];
int n = 10;
int ages[10];
typedef struct person people;
n = write(people);
print(people);
system("PAUSE");
return 0;
}
int write(struct person *people)
{
int i;
char name[41];
int age[10];
for(i=0; i<=i; i++)
{
fflush(stdin);
printf("Enter full name\n");
gets(people.name);
strcpy(names[i], name);
if(names[i][0] == '\0')
break;
printf("Enter their age\n");
scanf("%d", &age[i]);
ages[i] = age[i];
}
}
void print(struct person *people)
{
int i = 0;
for(i = 0; i < 10; i++)
{
if(names[i][0] == '\0')
break;
printf("%s is %d year(s) old\n", names[i], ages[i]);
}
return i;
}
You are passing the name of a type that you just defined instead of a variable declared of that type, this
typedef struct person people;
should be
struct person people;
Change
n = write(people);
to
n = write(&people);
Remove fflush(stdin) it's undefined behavior.
Do not use gets() it's very unsafe, use fgets() instead
char name[40];
gets(name);
should be
char name[40];
fgets(name, sizeof(name), stdin);

Resources