• C

I keep getting a fatal error LNK1120: 1 unresolved externals

I keep getting this fatal error and I don't know what it is for. I didn't get it until I added my loadFile and checkState functions.
#include <ctype.h>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <stdio.h>

struct customers
{
	int cust_id;
	char cust_name[28];
	static char states[3];
	char discount;
	double balance_due;
	int order_out;
};

struct myRecords
{
	customers rec[];
};

struct state
{
	char name[15];
	char abbr[3];
};

struct stateType
{
	state lists[51];
};

using namespace std;

void is_int(char [], char []);
void is_name(char [], char []);
void get_str(char[], char[]);
int checkState(struct stateType*, char[]);
void loadFile(FILE *, struct stateType*, char[]);

int main()
{
	myRecords table, *point_table;
	point_table = &table;

	stateType STname, *point_STname;
	point_STname = &STname;

	char buffer[50];
	char buf[50];
	char name[50];
	char state[3];
	int counter = 0;

	FILE *fp;
	fp = fopen("STATES.DAT", "r");
	if (fp == NULL)
	{
		printf ("Error opening file! ");
	}
	loadFile(fp, point_STname, buffer); 

	is_int("Please enter a customer id: ", buf);
	is_name("Please enter customer name: ", name);
	get_str("Please enter a state: ", state);
	checkState(point_STname, state);

}//end of main

/*****************************
*Function to get customer id *
*****************************/
void is_int(char prompt[], char buf[])
{
	
	printf("\n %s",prompt);
	gets(buf);
	int i;
	int id;
	int y=0;
	for (i=0; buf[i]; i++)
	{
			if (!isdigit(buf[i]))
			{
				is_int("Please enter a customer id: ", buf);
				system ("pause");
			}	
			else
			{				
				id = atoi(buf);
				if(id < 998 && id > 0)
				{
					printf ("It worked!");
					//table->rec[y].cust_id = buf;
				}
				else
				{
					is_int("Please enter a customer id: ", buf);
					system ("pause");
				}
			}
	}
}
/*******************************
*Function to get customer name *
*******************************/
void is_name (char prompt[], char name[])
{
	printf("\n %s",prompt);
	gets(name);
	if (strlen(name) == 0)
	{
		is_name("Please enter a customer name: ", name);
	}
	else
	{
		printf("It worked!");
		system("pause");
		//store to structure
	}
}
/********************************
*Load state file into structure *
********************************/
void loadFile (FILE *fp, struct stateType* STname, char buffer[])
{
	int counter = 0;
	
	while(!(feof(fp)))
	{
		fgets(buffer, 20, fp);
		STname->lists[counter].name[strlen(STname->lists[counter].name)-1] = '\0';
		fgets(STname->lists[counter].name, 20, fp);
		STname->lists[counter].abbr[strlen(STname->lists[counter].abbr)-1] = '\0'; 
		fgets(STname->lists[counter].abbr, 20, fp);
		++counter;
	}
	fclose(fp);
}
/******************************
*Binary search for  the state *
******************************/
int check_state (struct stateType* STname, char state[])
{
	int first=0, last = 50, middle, position=-1;
	bool found=false;
	while (!found && first <= last)
	{
		middle = (first + last) / 2;
		if (STname->lists[middle].abbr == state)
		{
			found = true;
			position = middle;
		}
		else if (STname->lists[middle].abbr > state)
		{
			last = middle - 1;
		}
		else
		{	
			first = middle + 1;
		}
	}
	
	if (position == -1)
	{
		printf ("Not a valid state abbreviation");
		get_str("Please enter a state: ", state);
	}
	else
	{
		printf ("This is a valid state");
		//store in structure
	}
	return position;
}
/*************************
*Function to get strings *
*************************/
void get_str(char prompt[], char state[])
{
	printf("\n %s",prompt);
	gets(state);
}

Open in new window

reesee324Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Kent OlsenData Warehouse Architect / DBACommented:
Hi reesee,

The message should tell you what external(s) aren't found.  Can you post it/them?


0
phoffricCommented:
See //@@ for two changes that make this compile:
#include <ctype.h>  
#include <iostream>  
#include <cstdlib>  
#include <cstdio>  
#include <stdio.h>  

struct customers  
{  
    int cust_id;  
    char cust_name[28];  
    static char states[3];  
    char discount;  
    double balance_due;  
    int order_out;  
};  

struct myRecords  
{  
    customers rec[1000];  //@@
};  

struct state  
{  
    char name[15];  
    char abbr[3];  
};  

struct stateType  
{  
    state lists[51];  
};  

using namespace std;  

void is_int(char [], char []);  
void is_name(char [], char []);  
void get_str(char[], char[]);  
int checkState(struct stateType*, char[]);  
void loadFile(FILE *, struct stateType*, char[]);  

int checkState(struct stateType*, char[]) { //@@
    return 0;
}
int main()  
{  
    myRecords table, *point_table;  
    point_table = &table;  

    stateType STname, *point_STname;  
    point_STname = &STname;  

    char buffer[50];  
    char buf[50];  
    char name[50];  
    char state[3];  
    int counter = 0;  

    FILE *fp;  
    fp = fopen("STATES.DAT", "r");  
    if (fp == NULL)  
    {  
        printf ("Error opening file! ");  
    }  
    loadFile(fp, point_STname, buffer);   

    is_int("Please enter a customer id: ", buf);  
    is_name("Please enter customer name: ", name);  
    get_str("Please enter a state: ", state);  
    checkState(point_STname, state);  

}//end of main  

/*****************************  
*Function to get customer id *  
*****************************/  
void is_int(char prompt[], char buf[])  
{  

    printf("\n %s",prompt);  
    gets(buf);  
    int i;  
    int id;  
    int y=0;  
    for (i=0; buf[i]; i++)  
    {  
        if (!isdigit(buf[i]))  
        {  
            is_int("Please enter a customer id: ", buf);  
            system ("pause");  
        }         
        else  
        {                                 
            id = atoi(buf);  
            if(id < 998 && id > 0)  
            {  
                printf ("It worked!");  
                //table->rec[y].cust_id = buf;  
            }  
            else  
            {  
                is_int("Please enter a customer id: ", buf);  
                system ("pause");  
            }  
        }  
    }  
}  
/*******************************  
*Function to get customer name *  
*******************************/  
void is_name (char prompt[], char name[])  
{  
    printf("\n %s",prompt);  
    gets(name);  
    if (strlen(name) == 0)  
    {  
        is_name("Please enter a customer name: ", name);  
    }  
    else  
    {  
        printf("It worked!");  
        system("pause");  
        //store to structure  
    }  
}  
/********************************  
*Load state file into structure *  
********************************/  
void loadFile (FILE *fp, struct stateType* STname, char buffer[])  
{  
    int counter = 0;  

    while(!(feof(fp)))  
    {  
        fgets(buffer, 20, fp);  
        STname->lists[counter].name[strlen(STname->lists[counter].name)-1] = '\0';  
        fgets(STname->lists[counter].name, 20, fp);  
        STname->lists[counter].abbr[strlen(STname->lists[counter].abbr)-1] = '\0';   
        fgets(STname->lists[counter].abbr, 20, fp);  
        ++counter;  
    }  
    fclose(fp);  
}  
/******************************  
*Binary search for  the state *  
******************************/  
int check_state (struct stateType* STname, char state[])  
{  
    int first=0, last = 50, middle, position=-1;  
    bool found=false;  
    while (!found && first <= last)  
    {  
        middle = (first + last) / 2;  
        if (STname->lists[middle].abbr == state)  
        {  
            found = true;  
            position = middle;  
        }  
        else if (STname->lists[middle].abbr > state)  
        {  
            last = middle - 1;  
        }  
        else  
        {         
            first = middle + 1;  
        }  
    }  

    if (position == -1)  
    {  
        printf ("Not a valid state abbreviation");  
        get_str("Please enter a state: ", state);  
    }  
    else  
    {  
        printf ("This is a valid state");  
        //store in structure  
    }  
    return position;  
}  
/*************************  
*Function to get strings *  
*************************/  
void get_str(char prompt[], char state[])  
{  
    printf("\n %s",prompt);  
    gets(state);  
}

Open in new window

0
reesee324Author Commented:
This is my whole output screen:
1>------ Build started: Project: Reynolds Assignment 4, Configuration: Debug Win32 ------
1>  Reynolds Assignment 4.cpp
1>c:\users\theresa\desktop\reynolds assignment 4\reynolds assignment 4\reynolds assignment 4.cpp(19): warning C4200: nonstandard extension used : zero-sized array in struct/union
1>          Cannot generate copy-ctor or copy-assignment operator when UDT contains a zero-sized array
1>c:\users\theresa\desktop\reynolds assignment 4\reynolds assignment 4\reynolds assignment 4.cpp(57): warning C4996: 'fopen': This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>          c:\program files\microsoft visual studio 10.0\vc\include\stdio.h(234) : see declaration of 'fopen'
1>c:\users\theresa\desktop\reynolds assignment 4\reynolds assignment 4\reynolds assignment 4.cpp(78): warning C4996: 'gets': This function or variable may be unsafe. Consider using gets_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>          c:\program files\microsoft visual studio 10.0\vc\include\stdio.h(277) : see declaration of 'gets'
1>c:\users\theresa\desktop\reynolds assignment 4\reynolds assignment 4\reynolds assignment 4.cpp(111): warning C4996: 'gets': This function or variable may be unsafe. Consider using gets_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>          c:\program files\microsoft visual studio 10.0\vc\include\stdio.h(277) : see declaration of 'gets'
1>c:\users\theresa\desktop\reynolds assignment 4\reynolds assignment 4\reynolds assignment 4.cpp(184): warning C4996: 'gets': This function or variable may be unsafe. Consider using gets_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>          c:\program files\microsoft visual studio 10.0\vc\include\stdio.h(277) : see declaration of 'gets'
1>c:\users\theresa\desktop\reynolds assignment 4\reynolds assignment 4\reynolds assignment 4.cpp(193): warning C4996: 'gets': This function or variable may be unsafe. Consider using gets_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
1>          c:\program files\microsoft visual studio 10.0\vc\include\stdio.h(277) : see declaration of 'gets'
1>  LINK : C:\Users\Theresa\Desktop\Reynolds Assignment 4\Debug\Reynolds Assignment 4.exe not found or not built by the last incremental link; performing full link
1>Reynolds Assignment 4.obj : error LNK2019: unresolved external symbol "int __cdecl checkState(struct stateType *,char * const)" (?checkState@@YAHPAUstateType@@QAD@Z) referenced in function _main
1>C:\Users\Theresa\Desktop\Reynolds Assignment 4\Debug\Reynolds Assignment 4.exe : fatal error LNK1120: 1 unresolved externals
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
0
Hey MSSPs! What's your total cost of ownership?

WEBINAR: Managed security service providers often deploy & manage products from a variety of solution vendors. But is this really the best approach when it comes to saving time AND money? Join us on Aug. 15th to learn how you can improve your total cost of ownership today!

Kent OlsenData Warehouse Architect / DBACommented:
Ok.

At line 19, you're going to have to assign a length to the array.  You've used 50 elsewhere for *name*, so 50 seems rational.

  int __cdecl

Hmm....  don't know why that's resolving to an error.  Let me dig a bit...


Kent
0
phoffricCommented:
You picked a C zone, yet the code is C++.
Are you compiling with C++ rather than C compiler?
Is your extension .c or .cpp ?
0
reesee324Author Commented:
Okay that worked but now I'm getting an error on my Search so I guess I'll have to figure that one out next :) Thanks!
0
Kent OlsenData Warehouse Architect / DBACommented:

On thing that you should strongly consider is changing calls to gets(), to calls to fgets(stdin).

gets() can result in a buffer overflow that could crash your program.  One of the parameters to fgets() is the buffer length.  The function won't return more data than the length that you pass to it.


Kent
0
reesee324Author Commented:
It's .cpp
0
phoffricCommented:
There appears to be a typo in your OP:
int checkState(struct stateType*, char[]); 
int check_state (struct stateType* STname, char state[])

Open in new window

0
phoffricCommented:
Search on //@@@ for the changes to get this to build:
#include <ctype.h>  
#include <iostream>  
#include <cstdlib>  
#include <cstdio>  
#include <stdio.h>  

struct customers  
{  
    int cust_id;  
    char cust_name[28];  
    static char states[3];  
    char discount;  
    double balance_due;  
    int order_out;  
};  

struct myRecords  
{  
    customers rec[1000];  //@@@
};  

struct state  
{  
    char name[15];  
    char abbr[3];  
};  

struct stateType  
{  
    state lists[51];  
};  

using namespace std;  

void is_int(char [], char []);  
void is_name(char [], char []);  
void get_str(char[], char[]);  
int checkState(struct stateType*, char[]);  
void loadFile(FILE *, struct stateType*, char[]);  

int main()  
{  
    myRecords table, *point_table;  
    point_table = &table;  

    stateType STname, *point_STname;  
    point_STname = &STname;  

    char buffer[50];  
    char buf[50];  
    char name[50];  
    char state[3];  
    int counter = 0;  

    FILE *fp;  
    fp = fopen("STATES.DAT", "r");  
    if (fp == NULL)  
    {  
        printf ("Error opening file! ");  
    }  
    loadFile(fp, point_STname, buffer);   

    is_int("Please enter a customer id: ", buf);  
    is_name("Please enter customer name: ", name);  
    get_str("Please enter a state: ", state);  
    checkState(point_STname, state);  

}//end of main  

/*****************************  
*Function to get customer id *  
*****************************/  
void is_int(char prompt[], char buf[])  
{  

    printf("\n %s",prompt);  
    gets(buf);  
    int i;  
    int id;  
    int y=0;  
    for (i=0; buf[i]; i++)  
    {  
        if (!isdigit(buf[i]))  
        {  
            is_int("Please enter a customer id: ", buf);  
            system ("pause");  
        }         
        else  
        {                                 
            id = atoi(buf);  
            if(id < 998 && id > 0)  
            {  
                printf ("It worked!");  
                //table->rec[y].cust_id = buf;  
            }  
            else  
            {  
                is_int("Please enter a customer id: ", buf);  
                system ("pause");  
            }  
        }  
    }  
}  
/*******************************  
*Function to get customer name *  
*******************************/  
void is_name (char prompt[], char name[])  
{  
    printf("\n %s",prompt);  
    gets(name);  
    if (strlen(name) == 0)  
    {  
        is_name("Please enter a customer name: ", name);  
    }  
    else  
    {  
        printf("It worked!");  
        system("pause");  
        //store to structure  
    }  
}  
/********************************  
*Load state file into structure *  
********************************/  
void loadFile (FILE *fp, struct stateType* STname, char buffer[])  
{  
    int counter = 0;  

    while(!(feof(fp)))  
    {  
        fgets(buffer, 20, fp);  
        STname->lists[counter].name[strlen(STname->lists[counter].name)-1] = '\0';  
        fgets(STname->lists[counter].name, 20, fp);  
        STname->lists[counter].abbr[strlen(STname->lists[counter].abbr)-1] = '\0';   
        fgets(STname->lists[counter].abbr, 20, fp);  
        ++counter;  
    }  
    fclose(fp);  
}  
/******************************  
*Binary search for  the state *  
******************************/  
int checkState (struct stateType* STname, char state[]) //@@@ 
{  
    int first=0, last = 50, middle, position=-1;  
    bool found=false;  
    while (!found && first <= last)  
    {  
        middle = (first + last) / 2;  
        if (STname->lists[middle].abbr == state)  
        {  
            found = true;  
            position = middle;  
        }  
        else if (STname->lists[middle].abbr > state)  
        {  
            last = middle - 1;  
        }  
        else  
        {         
            first = middle + 1;  
        }  
    }  

    if (position == -1)  
    {  
        printf ("Not a valid state abbreviation");  
        get_str("Please enter a state: ", state);  
    }  
    else  
    {  
        printf ("This is a valid state");  
        //store in structure  
    }  
    return position;  
}  
/*************************  
*Function to get strings *  
*************************/  
void get_str(char prompt[], char state[])  
{  
    printf("\n %s",prompt);  
    gets(state);  
}

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
reesee324Author Commented:
Oops...I've been looking at it for too long thanks :)
0
phoffricCommented:
You are welcome. Very easy to get confused with a slew of errors and warnings. You can add the _CRT_SECURE_NO_WARNINGS macro to your project properties to reduce the number of warnings.

Configuration Properties   ->   C/C++   ->   Preprocessor    ->   Preprocessor Definitions

Then add the macro, so it may look like this (note the semi-colon):
       _MBCS;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS
0
Kent OlsenData Warehouse Architect / DBACommented:

Reesee -- actually, hiding the warning from _CRT_SECURE_NO_WARNINGS is a bad idea.  They are warnings for a reason.

Better is to not use the deprecated functions.  Better still is to use the safe forms of the functions.


Kent
0
evilrixSenior Software Engineer (Avast)Commented:
>> Better is to not use the deprecated functions.  Better still is to use the safe forms of the functions.

This makes an interesting read.
http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=260
0
reesee324Author Commented:
Okay thanks for the info :)
0
phoffricCommented:
>> hiding the warning from _CRT_SECURE_NO_WARNINGS is a bad idea.
Microsoft would agree since to take their suggested changes means to abandon the standard ANSI/ISO C++ code that you have been writing, replacing it with non-portable code that only works if you use a Microsoft compiler.
0
Kent OlsenData Warehouse Architect / DBACommented:
@phoffric -- no one said to abandon the author's work.  I said to use the safe forms of the I/O functions.
0
phoffricCommented:
When the "safe forms" are not standard C++, I would not recommend using them.
0
Kent OlsenData Warehouse Architect / DBACommented:

If you don't want to use them, then don't.

But someone that's new to C and is writing a C program needs to be taught good habits.  The use of depricated, dangerous functions is not a good habit.  
0
phoffricCommented:
Someone new to C should stick with standard C, IMO; unless they need to use threads and POSIX as a requirement. If there are safer standard C functions, then by all means, they should be used.
0
Kent OlsenData Warehouse Architect / DBACommented:

  fgets () is standard C.  

  Feel free to look it up.
0
phoffricCommented:
>> fgets () is standard C;  Feel free to look it up.
You should look up fopen. It is standard also. Yet Microsoft suggests "Consider using fopen_s instead". And IMO, I would not recommend using this non-portable non-standard function.

If the compiler gave a helpful warning about gets saying to consider using fgets instead, then I would not suggest adding the _CRT_SECURE_NO_WARNINGS macro to remove these Microsoft warnings. But the warning in the above post is: "Consider using gets_s instead" - a non-portable, non-standard function that ties you to Windows and their Microsoft compiler.
0
evilrixSenior Software Engineer (Avast)Commented:
>> The use of depricated, dangerous functions is not a good habit.

*slaps forehead very hard* -- the standard posix and C/C++ functions are not deprecated by any stretch of the imagination -- except in Microsoft's little world, and due to pressure from the real C/C++ community and the fact the word "deprecated" has a very specific meaning in the standards documents they have since rescinded this term as it was both inappropriate and arrogant for them to use it against standard functions over which they have no jurisdiction.

The article I posted above (by Danny Kalev who is a former member of the C++ standards council, and a Brit like me :) ) shows these "safe" functions are far from it! They are actually more dangerous because they lead the programmer into a false sense of security and actually provide limited (or no) protection in many situations. It is far better to stick to standard functions that have well known behaviour and learn how to use them properly and how to code defensively to avoid the problems these "safe" functions try (and fail) to protect against.

Without specifically meaning to take sides (and I do hate to disagree with another ZA) but I'm afraid I'm with phoffric on this one :)

I'll go crawl back under my stone now and let you two carry on.
0
Kent OlsenData Warehouse Architect / DBACommented:
Hi Rix,

It has long been the practice here to suggest to C coders that gets () is a dangerous function with side effects that generally escape new programmers, specifically buffer overrun.  That suggestion has included a description of fgets () and how it can be used to prevent the overrun.  


Part of what seems to be going on here is just language.  It's a pretty common occurrence on EE or most any of the international boards.  I didn't mean to suggest that the function(s) were deprecated across all platforms, merely echoing the language that the compiler produced.

The C forum is generally a teaching forum as it has a high percentage of newcomers to programming.  This thread is a good example of how we, as experts, can do a better job of answering newcomers' questions.  What behavior can one expect when compiling C code as C++ code?  What do these error messages and warnings mean?  Why does the compiler say that the function is deprecated?  Is disabling warnings a good idea and how does it affect my program?  Why are there better choices than gets()?

At the end of the day, the original question was answered, yet the asker was left with more questions than when he first posted.  One or two sentences of "why" go a long way when answering the "what" and "how" questions.


Kent
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C

From novice to tech pro — start learning today.