I'm trying to code build and run the program but this error message came out :
'MAX_BOOK_NAME' undeclared (first use in this function)
Another issue I'm facing is for the program to require and implement the following:
You must use the following struct to store information about one book:
struct book {
char *title;
char *author;
char *subject;
};
You must use the following struct to store information about the library collection:
struct library {
struct book collection;
int num_books;
struct library *next;
};
The only function you are specifically required to write is a copy function, which copies the contents of one book into another book. Here is the prototype for that function:
void copybook(struct book* dest, struct book* source);
Though the rest of the function prototypes will not be given, it is expected that you follow good programming design and create several functions with well-specified tasks related to the solution of this problem. Make sure to pay very careful attention to parameter passing. In particular, in each function that needs a variable of type struct library, make sure to pass the variable by reference, as follows:
void addBook(struct library* thislib);
This will ensure that any change made to the library in the function is reflected in main. Inside a function like this one, remember to access either component, use the following expressions:
thislib->collection
thislib->num_books
Whenever you add a book to the collection, make sure you add it to the end of the collection. Do not forget to update the variable num_books in the struct library variable.
Whenever you delete a book from the collection, make sure you copy the book in the second-last slot into the vacated spot. For example, if the book to be deleted is in position 3 and the number of books in the collection before deleting is 7, then the book in position 6 (the second-last filled position) should be moved to the book in index 3. Subsequently, the number of books in the library should be updated to hold only 6.
Below is what I had done so far,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void viewBooks()
{
int found = 0;
char bookName[MAX_BOOK_NAME] = {0};
{
s_BooksInfo_addBookInfoInDataBase = {0};
FILE *fp = NULL;
int status = 0;
unsigned int countBook = 1;
headMessage("VIEW BOOKS DETAILS");
fp = fopen(FILE_NAME,"rb");
if(fp == NULL)
{
printf("File is not opened\n");
exit(1);
}
if (fseek(fp,FILE_HEADER_SIZE,SEEK_SET) != 0)
{
fclose(fp);
printf("Facing issue while reading file\n");
exit(1);
}
while (fread (&addBookInfoInDataBase, sizeof(addBookInfoInDataBase), 1, fp))
{
printf("\n\t\t\tBook Count = %d\n\n",countBook);
printf("\t\t\tBook id = %u",addBookInfoInDataBase.books_id);
printf("\n\t\t\tBook name = %s",addBookInfoInDataBase.bookName);
printf("\t\t\tBook authorName = %s",addBookInfoInDataBase.authorName);
printf("\t\t\tBook issue date(day/month/year) = (%d/%d/%d)",addBookInfoInDataBase.bookIssueDate.dd,
addBookInfoInDataBase.bookIssueDate.mm, addBookInfoInDataBase.bookIssueDate.yyyy);
found = 1;
++countBook;
}
fclose(fp);
if(!found)
{
printf("\n\t\t\tNo Record");
}
printf("\n\n\t\t\tPress any key to go to main menu.....");
fflush(stdin);
getchar();
}
return 0;
}
In the current .c file you showed us, the MAX_BOOK_NAME is not defined. In order to do that you must add the folloing line of code right bellow the #include lines but outside of any function because you want it to be visible int the whole file:
#define MAX_BOOK_NAME the_number_you_want
The problem is that the size of the bookName arrays is nowhere given it is a constant and either needed to be declared after the preprocesser directive like or inside the main function like,
#define MAX_BOOK_NAME = 10; //The number is given just for example
or
const int MAX_BOOK_NAME = 10; //The number is given just for example
The constant named MAX_BOOK_NAME is not defined in the whole piece of code you shared with us. I guess you should try defining the constant before using it. Try putting :
#define MAX_BOOK_NAME 10// or any number you need
void viewBooks()
{
int found = 0;
char bookName[MAX_BOOK_NAME] = {0};
{
or
const int MAX_BOOK_NAME=10//or any number you wish
void viewBooks()
{
int found = 0;
char bookName[MAX_BOOK_NAME] = {0};
{
if your wish was to make a dynamic array then you could try this link
if your problem was just not to define the constant then you already got many answers from others as well.
Related
So I've been looking at structures, functions and pointers for days now. I just cant wrap my head around structures good enough to do what I want...
I was trying to write a function, which was originally going to receive user input (taken with fgets) as an argument. I have put that aside now, and just decided to give the function a single argument. That argument will be the name of a struct, and I'll use that name to access it's variables and print them the way I want.
typedef struct
{
int hp;
char *name;
} bare;
bare example;
void print_info(char *name);
int main()
{
example.hp = 5;
strcpy(example.name,"John");
print_info("example");
}
void print_info(char *name)
{
printf("The hp of %s is %d", (*name), (*name)->hp);
}
Whatever bloody thing I put there instead of char *name, it always ended up giving me the error "error: struct or union expected"! I tried struct bare **name and (*name)->hp/(*name).hp, char *name/**name and *&name.hp, *&name->hp, every possible solution I could think of..! i think they all turned out to be nonsense... I just cant wrap my head around pointers and structs enough to do this! A little help please? I searched high and low on function arguments, pointers and structs, yet couldn't find a solution/question like mine..
First, it's better to declare your struct this way:
typedef struct bare {
int hp;
char *name;
} bare;
Second, avoid global variable as much as you can. I don't see the point of declaring example in the global namespace since you are using it only inside main().
Third, this line has a problem:
strcpy(example.name, "John");
You are attempting to copy "John" to an uninitialized pointer (example.name) that points to some random memory address. You have to either allocate enough space using malloc() (and free it when you're done with it), or use a fixed-length array. Moreover, it's better to use strncpy() because it allows to specify the maximum number of characters to copy. This way you avoid the risk of buffer overflow.
Fourth, to avoid copying your entire struct to print_info() (in fact, any other struct to any other function), you should pass its address.
With all that said, here is how your code should be written:
#include <stdio.h>
#include <string.h>
typedef struct bare {
int hp;
char name[100]; // Make sure it has enough space, or use malloc() if you don't know how much it will hold initially
} bare;
void print_info(bare *name);
int main(void)
{
bare example; // Declare it inside main()
example.hp = 5;
strncpy(example.name, "John", sizeof example.name); // This works and is safe
print_info(&example);
}
void print_info(bare *name)
{
printf("The hp of %s is %d", name->name, name->hp);
}
Output:
The hp of John is 5
I think what you wish to do is this:
#include <stdio.h>
#include <string.h>
typedef struct {
int hp;
char *name;
} bare;
bare example;
void print_info(bare *name);
int main() {
example.hp = 5;
strcpy(example.name, "John");
print_info(&example);
}
void print_info(bare *name) {
printf("The hp of %s is %d", name->name, name->hp);
}
Or if you want to pass example by value:
#include <stdio.h>
#include <string.h>
typedef struct {
int hp;
char *name;
} bare;
bare example;
void print_info(bare name);
int main() {
example.hp = 5;
strcpy(example.name, "John");
print_info(example);
}
void print_info(bare name) {
printf("The hp of %s is %d", name.name, name.hp);
}
Why did your code not work?
print_info had an incorrect argument data type. What you wanted was to pass an object of bare or perhaps a pointer to an object of bare, but you were instead passing a variable of type char *.
The arrow operator is used on pointers. Maybe take a look at Arrow operator (->) usage in C.
You wanted to pass in a string typed in by the user.
I was trying to write a function, which was originally going to receive user input (taken with fgets) as an argument. I have put that aside now, and just decided to give the function a single argument.
This explains why you pass in a char * to your function. The input value was originally going to be read from fgets. In your program, you passed in the name of your variable.
bare example;
/* ... */
print_info("example");
To do a dynamic lookup on a symbol name, use dlsym.
As I suggested in comments, if you want to be able to look up the name of a variable to find the associated object, you can use dlsym so long as you are on a POSIX system (like Linux). For example:
// Need to inlcude <dlfcn.h> and link with -ldl
// Make local variables findable with -rdynamic
void print_info(char *name)
{
bare *p = dlsym(0, name);
if (p != NULL)
printf("The hp of %s is %d", p->name, p->hp);
else
printf("%s not found!\n", name);
}
So long as you include <dlfcn.h> and use -ldl when linking the program, and you make your symbol table visible (with -rdynamic on GCC), the program will find the pointer to your example variable. (Try it online!)
But you probably meant to do a lookup by name.
However, you seemed to have mixed some things up. Usually, the user will not care what names you have used for the variables in your program. You would never expect fgets to give you "example" because that is not what the user would type in.
You probably meant to search for the bare record that matches the name parameter of bare. In your case, "John".
print_info("John");
Normally, you would have a table of bares that you would look over and check for a match. However, in your simplified example, there is only one to check.
bare * find_bare(char *name)
{
if (strcmp(name, example.name) == 0) return &example;
return NULL;
}
void print_info(char *name)
{
bare *p = find_bare(name);
if (p != NULL)
printf("The hp of %s is %d", p->name, p->hp);
else
printf("%s not found!\n", name);
}
It isn't hard to create and search a table of bare.
In this case, you could probably simple create an array of bare to represent your collection that you would search over.
#define BARE_TABLE_SIZE 50
bare table_example[BARE_TABLE_SIZE];
Assuming you add the code to populate your table, you could use a simple loop to search for a matching name.
bare * find_bare(char *name)
{
for (int i = 0; i < BARE_TABLE_SIZE; ++i)
{
if (strcmp(name, table_example[i].name) == 0)
return &table_example[i];
}
return NULL;
}
Your example.name was an uninitialized pointer.
Finally, the most egregious error in your program is the attempt to call strcpy on an uninitialized pointer. One solution is to allocate new memory to hold the new name and assign the location of the new name to the pointer. POSIX systems (like Linux) supply a function called strdup that creates a copy of the input for you, in newly allocated memory.
example.name = strdup("John");
Since the memory is allocated by malloc, you would need to call free on the pointer if example is ever recycled for a new name.
I made a simple dictionary code, and surfed for an hour, and I found a file I/O code. But my compiler(I use Microsoft visual C++) says my code(unfortunately, the core part of the code) is wrong. but I can't get it. What is actually wrong and why???
/*
DosDic ver 1.0.0 2015-07-03
*/
#include<stdio.h>
#include<string.h>
char key = 0;
FILE *fp; //set a file pointer var
fp = fopen("dicdata.dat","r"); //open a file
int b = 0;
int trial = 0;
char result[];
char searchfor[] = fp; //save a whole list of dictionary in a var
int i;
char sb[]; //var for search in a list
int getsearchtrial(char sb[]){
for(i=0;i=strlen(sb);i++){ //how much I tried to reach to the word
switch((int)searchfor[b]-(int)sb[i]){ //are two alphabets same?
case 0 :
default : i=0;
}
b++; //keep finding in a list
trial++; //try again
}
return trial;
}
int adress;
int mainpage(){
printf("Type what you want to search : ");
scanf("%c",sb[ ]);
getsearchtrial(sb[ ]) - strlen(sb[ ]) = adress; //where the word is located in the list
for(i = adress;i = adress + 30; i++){ //print
printf("%c",searchfor[i]);
}
printf("Thank you for using DosDic ver.1.0!"); //thank you!
}
void main(){ //call all those functions
mainpage();
fclose(fp); //close list
}
//and whats wrong with this? i cant even get it, but it's not working
Multiple issues.
First of all, you can't assign the result of fopen to fp outside the body of a function; you must move fp = fopen("dicdata.dat", "r"); to within the body of one of your functions (getsearchtrial most likely).
Secondly, you don't read from a file by simply assigning a file pointer to an object; you must use a library function like fscanf or fread or fgets. Assuming your file contains a single string of length 80, you'd need to write something like
char searchfor[81] = {0}; // make sure string is initially empty,
// extra space for string terminator
if ( !fgets( searchfor, sizeof searchfor, fp) )
{
// error reading from file
}
Of course, this depends on how your input file is structured. If it contains a list of strings, then you'll need to use a multidimensional array (or some other structure).
Third, when you declare an array, must specify its size before you can use it. result and searchfor are incomplete array definitions.
Finally, this line
getsearchtrial(sb[ ]) - strlen(sb[ ]) = adress;
needs to be reversed; the target of an assignment must be on the left of the assignment operator.
You need to step back and learn how to write C code from the ground up.
There is so much wrong I'm not even going to itemise it all here - most of it seems to stem from your lack of understanding of arrays in C.
Most notably...
You can't declare an array and not initialise it or specify a size.
You can't assign a FILE * to a char array (and expect decent
results).
You can't execute a statement like fp = fopen at the
global scope like you are.
Try this tutorial and you may fix 95% of your problems, then go from there.
So I'm working on a little C program which is a little address book that automatically allocates memory when you add a new contact in it.
I'm using two typedef structures, the first one stores the info on the contact (name telephone etc.):
typedef struct
{
char nom[TAILLE1];
char tel[TAILLE2];
} CONTACT;
The seconde one contains a int with the number of contacts in the address book and an other one is the pointer to the other structure.
typedef struct
{
int nb;
CONTACT * contacts; // tableau
} LISTE_TABLEAU;
I created a function to import contact from a TXT file (first line the name of the person, second line their telephone number and so on). I simplified it with only the basic
int lireDonneesTxt(LISTE_TABLEAU* tab)
{
int i;
tab->contacts = (CONTACT *)malloc(sizeof(CONTACT)*13); (13 because there are 13 contact for testing purposes)
i = 0;
while( !feof(entree) )
{
fgets(ligne, TAILLE1, entree);
strcpy(tab->contacts[i].nom, ligne);
fgets(ligne, TAILLE1, entree);
strcpy(tab->contacts[i].tel, ligne);
i++
}
return 1;
}
When I compile my code there isn't any issue, no warning what so ever.
But when I run my code everything works great until I try and print a name on the screen, then the executable file crashes.
My main function looks something like this:
int main(void)
{
LISTE_TABLEAU *tabb;
tabb->nb = 0;
lireDonneesTxt(&tabb);
printf("%s", tabb->contacts[0].nom);
return 0;
}
If I add the same printf that is in the main at the end of my lireDonneesTxt function it prints the name without any problem.
I'm guessing that the data is not passed correctly to the structure.
I am now blocked and have no idea what to try to make this work !
Don't pass the address of the LISTE_TABLEAU pointer here:
lireDonneesTxt(&tabb);
just pass the pointer
lireDonneesTxt(tabb);
Also setting tabb->nb = 0; to unalocated memory is undefined behaviour.
The memory is not allocated for "tabb" & you are trying to access its member variable (tabb->nb) in main() function. It is illegal, thus the run time crash.
You can try the below code instead:
int main(void)
{
LISTE_TABLEAU tabb;
tabb.nb = 0;
lireDonneesTxt(&tabb);
printf("%s", tabb.contacts[0].nom);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define RECORDS 10
The function below is what I am asking for help with.
static char searchforRecordbystate(char input[3])
{
for / while /if loop
search struct array members
if a match is found
return (print) the entire struct where a match was found
return 0;
}
Main function - first time ever using pointers, (xcode is not complaining with it set to be as strict as possible) but all of you are welcome to complain, especially if I am making a huge oversight.
int main() {
typedef struct {
char *firstName[RECORDS];
char *lastName[RECORDS];
char *street[RECORDS];
char *city[RECORDS];
char *state[RECORDS];
int *zip[RECORDS];
char *phone[RECORDS];
int *accountId[RECORDS];
} Customer ;
typedef int records;
records i = 0;
array loop for data entry
Customer custArray[RECORDS];
printf("================================================================\n");
for(i = 0; i < RECORDS; ++i)
{
printf("Enter data for customer %d\n", i + 1);
printf("Enter firstname, last name, phone\n");
scanf("%s %s %s", *custArray[i].firstName, *custArray[i].lastName, *custArray[i].phone);
printf("Enter Address (Street City State ZIP)");
scanf("%s %s %s*c %d", *custArray[i].street, *custArray[i].city, *custArray[i].state, *custArray[i].zip);
break;
}
char input[3];
printf("Enter in state to search for customer a customer record:\n");
scanf("%s", input);
searchforRecordbystate(input);
}
No error checking necessary, just trying to crawl into learning c at the moment. And there will not be duplicate data in the state member. Hope that makes this easier.
how would I write a search function to look for a match in a struct
array and return (printf) the entire struct it matched?
Declare the struct datatype outside of the function so it's "visible" to the whole module.
Create a function that is able to pretty-print a struct:
void CustomerPrint(const Customer *toPrint) {
...
}
Create a search function that iterates through the array comparing given arguments:
Customer *CustomerFind(const char *name) {
...
}
Connect the two function blocks by calling CustomerFind and in case the result is not NULL call the CustomerPrint function.
Of course the interfaces are only proposal and are subject to be changed. If you've got any questions regarding the details of the proposal leave a comment, I'll explain it in great detail if you like.
Additional thoughts
While rereading my post I realized that some of my decisions I've made in above proposal need an explaination anyway:
In CustomerPrint the pointer taken is `const? because this function is not going to modify any field of the struct. Therefore we tell the compiler that we are not going to change anything.
CustomerFind is expected to have arguments for all searchable fields. (So you are encouraged to extend the signature) I'd propose to take all the "compare" values by pointer and let the caller those pointers be NULL which are not relevant for the search. (e.g. if you have name and city you can leave city NULL in order to only search for the first occurence of name.
The function itself runs through the array of records and compares the fields that are not NULL. In case it finds one, it returns the pointer to that element (return &(myRecords[n]);). If the function comes to the end of the array, it will return NULL to indicate no record matched.
There is also a concept you can introduce if you want to have "search - search next" capabilities. Let me know if you are intrested in a concept for that too.
typedef struct {
char firstName[NAMEMAX];
char lastName[NAMXMAX];
char street[STREETMAX];
char city[CITYMAX];
char state[STATEMAX];
int zip;
char phone[PHONEMAX];
int accountId;
} Customer ;
Customer Customers[RECORDS];
static int searchforRecordbystate(char input[]) {
for (int i = 0; i < RECORDS; i++) {
if (strcmp(input, Customers[i].state) == 0) {
printCustomer(Customers[i]);
return i;
}
}
return -1; // Not found
}
Writing printCustomer() is an exercise for the reader.
We were given an assignment in our C programming class to modify a program to make it more object oriented. Part of this was to fix the toString method. The directions were:
Modify the Student module to make it more object-oriented.
* Each Student object should have a function pointer that points to an
appropriate function for producing a string representation of the object.
* Provide a default toString method to each object when it is created.
The studentToString method should no longer be part of the Student interface
(as defined in Student.h)
However, we aren't really sure what this means and would like to know if we are on the right track with what we are suppose to do. Here is the code from the Student.c file:
#include <stdio.h>
#include <stdlib.h>
#include "Student.h"
#include "String.h"
static void error(char *s) {
fprintf(stderr, "%s:%d %s\n", __FILE__, __LINE__, s);
exit(1);
}
extern Student newStudent(char *name, int age, char *major) {
Student s;
if (!(s = (Student) malloc(sizeof(*s))))
error("out of memory");
s->name = name;
s->age = age;
s->major = major;
return s;
}
extern char *studentToString(Student s) {
const int size = 3;
char age[size + 1];
snprintf(age, size, "%d", s->age);
char *line = newString();
line = catString(line, "<");
line = catString(line, s->name);
line = catString(line, " ");
line = catString(line, age);
line = catString(line, " ");
line = catString(line, s->major);
line = catString(line, ">");
return line;
}
We known that the *studentToString method will be replaced by a *toString method and we think that the *toString method will have the same contents as the *studentToString method. But we don't understand how that makes it more object-oriented.
We have also determined, from the directions, that when we create a new Student object, we should have a pointer in the newStudent method that points to the new toString method.
We're not looking for anyone to do the program for us. We just want to understand what we are suppose to do as our professor has been out of town for the week. Any help would be greatly appreciated.
It sounds like he's asking you to take the Student structure and add a pointer to a function inside the structure itself so that when you have a valid pointer to a Student structure you can do something like
`myStudent->toString();`
and have it return the same value as
`studentToString(myStudent)`
would have before. This makes it more object oriented because of the fact that you're calling a toString method on an effective "instance" (for lack of better terms) of a Student structure and returning parameters related to that "instance." Just as you would in some sort of object-based programming language.
My guess is that you need to add a member to the Student struct, the type of that member would be a function pointer.
Then define that function.
Then add a parameter taking a function pointer to newStudent.
Then set that newly created member to the value of the parameter.
(this feels like an extremely abstract way to learn OO, but that's just my opinion)
Looks like your prof set you this problem so that you get an understanding of polymorphism. In this example, the idea is that every object in your system should have its own way of rendering itself as a string but you don't want to know the details; you just want to be able to call toString on any object.
E.g.
banana->toString()
apple->toString()