Related
I'm given a task to write a program that checks a piece of code, maximum of 20 lines of code, when the program runs you type in a function name, number of lines of code and type in the codes.
It's meant to search in the code and return if the function name you entered is a Library Function or User Defined Function or No Function if it doesn't find it, the code I've written is below, it doesn't work because I made mistakes and I've been trying to fix it but can't seem to figure it out, and I tried debugging to see where I made mistake, and I figured that in the function SearchRealisation it returns an error that
Run-Time Check Failure #2 - Stack around the variable 'buff' was
corrupted.
This program sample returns Library function instead of user defined function
type the function name: addition
Get count string in code: 9
int addition(int num1, int num2)
{
int result = num1 + num2; //trial
return result;
}
int main()
{
addition(8, 9);
}
Output is Library Function but correct output should be User Defined Function since it was defined in the code
void InputText(int length, char Text[MAX_STRINGS][MAX_COLUMNS])
{
//Repeat by Count String
gets_s(Text[0]);
for (int i = 0; i < length; i++)
gets_s(Text[i]);
//Output a string (starting with � zero and ending with Count String-1)
}
void OutMesseg(int param)
{
//Display one of three messages according to the parameter
if (param == -2)
printf("%s", "user defined function");
else if (param == -1)
printf("%s", "no function");
else
printf("%s", "library function");
}
char* DeleteComentsInString(char Text[MAX_STRINGS], char New[MAX_STRINGS])
{
char* a = strstr(Text, "//");
int len = strlen(Text);
if (a != NULL) len -= strlen(a);
strncpy(New, Text, len);
New[len] = '\0';
return New;
}
bool IsTypeC(char Word[MAX_STRINGS])
{
char ctype[6][MAX_STRINGS] =
{
"int",
"bool",
"char",
"float",
"double",
"void"
};
for (int i = 0; i < 6; i++)
{
if (strstr(Word, ctype[i]) != 0)
return true;
}
return false;
}
int SearchRealisation(int length, char Text[MAX_STRINGS][MAX_COLUMNS], int index_fanc, int& end)
{
int count = 0;
int start = -1;
end = -1;
char buff[MAX_STRINGS];
//Find first {
for (int i = index_fanc + 1; i < length && !count; i++)
{
if (strstr(DeleteComentsInString(Text[i], buff), "{") != NULL)
{
count++;
start = i;
}
}
//find last }
for (int i = start + 1; i < length && count; i++)
{
if (strstr(DeleteComentsInString(Text[i], buff), "{") != NULL)
count++;
else if (strstr(DeleteComentsInString(Text[i], buff), "}") != NULL)
count--;
if (!count)
end = i;
}
if (end == -1)
start = -1;
else
return start;
}
int SearchFunction(int length, char Text[MAX_STRINGS][MAX_COLUMNS], char FunctionName[MAX_COLUMNS], int& end)
{
//bool flag = false;
char commentDel[120];
int in;
for (int i = 0; i < length; ++i)
{
DeleteComentsInString(Text[i], commentDel);
if (strstr(commentDel, FunctionName) != NULL)
{
in = strlen(commentDel) - strlen(strstr(commentDel, FunctionName));
if ((in == 0 || (in != 0 && commentDel[in - 1] == ' ')) && (commentDel[in + strlen(FunctionName)] == ' ' || commentDel[in + strlen(FunctionName)] == '(') && strstr(commentDel, ";") == NULL)
{
return SearchRealisation(length, Text, i, end);
}
}
}
end = -1;
return -1;
}
int SearchResult(int length, char Text[MAX_STRINGS][MAX_COLUMNS], char FunctionName[MAX_COLUMNS])
{
int index;
int end;
int start = SearchFunction(length, Text, FunctionName, end);
if (start == -1)
return -1;
index = SearchFunction(length, Text, FunctionName, end);
if (index < 0)
return -2;
return index;
}
int findFunction(char string[MAX_STRINGS][MAX_COLUMNS], char* functName, int M)
{
return 0;
}
int main()
{
int length = 0;
char Code[MAX_STRINGS][MAX_COLUMNS] = { 0 };
char FunctionName[MAX_COLUMNS];
//char ConstantName[MAX_STRINGS];
printf("type the function name: ");
scanf("%s", &FunctionName);
printf("Get count string in code: ");
scanf("%d", &length);
InputText(length, Code);
printf("\n");
OutMesseg(SearchResult(length, Code, FunctionName));
return 0;
}
Well, you have been given a very difficult task:
There's no way to check this, as functions are resolved by a dynamic process that depends on your filesystem state, which is not available at runtime, after you have already compiled your program.
How do you distinguish a function that is compiled in a separate (but user defined) compilation unit from a system defined function? (e.g. double log(double);) that is defined in a math library? There is no way: the linker gets both from a different place (in the first case it gets it from the place you compiled the separate module, in the system case it gets it from a common library directory that has all the system related functions), but you don't have that information available at runtime).
In order to do this task feasible, you'd at least have the full set of source code files of your program. Preprocess them with the cpp(1) preprocessor (so you bypass all the macro expansion invocations) and then check for all function calls in the source code that are not provided in the full set of sources you have. This is quite similar to what the linker does. After compilation, the compiler leaves an object file with the compiled code, and a symbol table that identifies all the unresolved identifiers, and more important all the provided identifiers from this module. The linker then goes on all your modules trying to solve the unknowns, and for each that it doesn't have a solution in your code, it goes to the library directory to search for it. If it doesn't find it in either one, it fails telling you something is wrong.
In my opinion, you have been given a trap task, as the C language preprocess its input (this is something you should do, as many functions are hidden in the internals of macro bodies), then parse the code (for this, you need to write a C parser, which is no trivial task) to select which identifiers are defined in your code and which aren't. Finally you need to check all the calls you do in the code to divide the set in two groups, calls that are defined (and implemented) in your code, and calls that aren't (implemented, all the calls the compiler needs must be defined with some kind of prototype).
It's my opinion, but you have not a simple task, solvable in a short program (of perhaps one hundred lines) but a huge one.
Thanks a lot to everyone that answered I came up with a way to search the code for function definition and thereby return a value if its defined or not, or not even found, might not be the best solution to the task but works so far
I keep receiving an error regarding malloc and I'm trying to find out how to get this code to work without using stdlib.h in the header. Just stdio.h, is this possible and how? As I'm totally confused
#include <stdio.h>
void allocate(int* score_array, const int input)
{
int iter;
for(iter = 1;iter <= 11;++iter)
{
if( (input < iter*10) && (input >= (iter-1)*10 ) )
{
++(score_array[iter-1]);
}
}
}
void printf_star(const int len)
{
int iter;
for(iter = 0;iter < len;++iter)
{
printf("*");
}
printf("\n");
}
int main()
{
int iter, size, temp;
int* buffer;
int score_array[11];
for(iter = 0;iter < 11;++iter)
{
score_array[iter] = 0;
}
printf("How many grades will you be entering?\n");
printf("Enter a number between 1 and 100: ");
scanf("%d", &size);
buffer = (int*)malloc(size*sizeof(int));
for(iter = 1;iter <= size;++iter )
{
printf("Getting grade %d. You have %d grade(s) left to enter\n", iter, size-iter+1);
printf("Enter a number between 0 and 100: ");
scanf("%d",&temp);
if( (temp>=0) && (temp <= 100) )
{
buffer[iter-1] = temp;
}
else
{
do
{
printf("Invalid Value!\n");
printf("Getting grade %d. You have %d grade(s) left to enter\n", iter, size-iter+1);
printf("Enter a number between 0 and 100: ");
scanf("%d",&temp);
}
while( (temp < 0) || (temp > 100) );
}
}
for(iter = 1;iter <= size;++iter)
{
allocate(score_array, buffer[iter-1]);
}
for(iter = 0;iter < 11;++iter)
{
printf_star(score_array[iter]);
}
return 0;
}
I keep getting this error:
hw08.c: In function ‘main’:
hw08.c:56: warning: incompatible implicit declaration of built-in function ‘malloc’
This is only a warning, not an actual error, so the program still compiles.
To eliminate the warning you can declare the malloc in your file:
#include <stdio.h>
extern void * malloc(unsigned long);
You could also just include stdlib.h, unless you have a major reason not to.
Header files just define the functions prototypes by using the extern keyword. The actual implementation of malloc resides in libc depending on the OS.
Not defining a function/system call prototype is indeed a warning, not a compile-time error, contrary to what many have conveyed in the comments!
Coming to the actual workaround, if you want to avoid using the #include <stdlib.h>, you either need to use:
#include <malloc.h> (deprecated since c89)
Define the header all by yourself, with extern void * malloc(size_t);
Credits to #Chris Rouffer too! :)
You need to include stdlib.h if you want to access the malloc() function, because that is where it is defined. Otherwise the compiler doesn't know what to do.
You really are supposed to include the header in your code if you want to use the function, however, in theory you could just paste the implementation of malloc() in your source and then use it from there without the header. This is a bad idea however, since anybody looking at the code would expect malloc() to refer to the standard implementation defined in stdlib.h.
I'm making an application in C that will use text menus. So, I decided to create a global array containing all the menus. As a workaround of an issue I will mention later, the code looks like this:
char* main_menu[]=
{"Refresh rate", "Help", "Default config", NULL};
char* other_stuff[]=
{"Stuff", "More", NULL};
char** screens[]={main_menu, other_stuff};
And I can use those strings like: screens[0][1] meaning first (or rather second, since we count from zero) option in zeroth/first menu.
It works, but it strikes me as quite inelegant that I had to declare those auxilliary arrays (main_menu and other_stuff). I tried to make use of nested brace initialization of arrays, but always the compiler would complain. Also, before you suggest declaring the array as, say, char* screeens[10][5] - there should be no magic numbers, as this is equally inelegant for me.
I tried:
char** screens[]={
{"Refresh rate", "Help", "Default config", NULL},
{"Stuff", "More", NULL}
};
However, the compiler gives me a warning (and rightfully, as accessing elements yields gibberish):
../main.c:96:1: warning: braces around scalar initializer [enabled by default]
{"Refresh rate", "Help", "Default config", NULL},
^
../main.c:96:1: warning: (near initialization for ‘screens[0]’) [enabled by default]
../main.c:96:1: warning: initialization from incompatible pointer type [enabled by default]
../main.c:96:1: warning: (near initialization for ‘screens[0]’) [enabled by default]
../main.c:96:1: warning: excess elements in scalar initializer [enabled by default]
and so on.
If I change the first line to char* screens[][]={, the compiler won't compile the code at all, giving error: error: array type has incomplete element type.
I'm writing in embedded evironment (avr-gcc 4.8.1), where memory is quite scarce, so I don't want to declare arrays bigger than necessary, thus wasting memory. Is there anything I can do, or is this as simple as possible?
Assuming you have C99 or later, you can use 'compound literals' to initialize your array:
#include <stddef.h> // NULL
char **screens2[] =
{
(char *[]){ "Refresh rate", "Help", "Default config", NULL },
(char *[]){ "Stuff", "More", NULL },
};
Or, if you want to be const-correct (a good thing — thanks to M.M and his comment):
char const * const * screens3[] =
{
(char const * const []){ "Refresh rate", "Help", "Default config", NULL },
(char const * const []){ "Stuff", "More", NULL },
};
Compilation (clean — no warnings or errors):
gcc -std=c11 -O3 -g -Wall -Wextra -Werror -pedantic -c 2das.c
(GCC 5.1.0 on Mac OS X 10.10.5)
I'm making an application in C that will use text menus.
You could try something like this:
#include <stdio.h>
#include<unistd.h>
typedef int (*menu)(void);
void clearScreen(int x){
int i=0;
for(;i<x;i++){
printf("\n");
}
}
int exitMenu(void) {
clearScreen(100);
printf("Exiting... Goodbye\n");
sleep(1);
return 0;
}
int mainMenu(void){
clearScreen(100);
printf("\t\t\tMain Manu\n");
return 0;
}
int updateSystem(void) {
clearScreen(100);
printf("System update...\n");
sleep(1);
return 1;
}
int installVlcFromPpa(void) {
clearScreen(100);
printf("Install VLC from PPA \n");
sleep(1);
return 0;
}
int installVlcFromSource(void) {
clearScreen(100);
printf("Install VLC from Source \n");
sleep(1);
return 0;
}
int uninstallVLC(void) {
clearScreen(100);
printf("Uninstall VLC... \n");
sleep(1);
return 1;
}
int chooseOption(int min, int max){
int option,check;
char c;
do{
printf("Choose an Option:\t");
if(scanf("%d%c",&option,&c) == 0 || c != '\n'){
while((check = getchar()) != 0 && check != '\n');
printf("\tThe option has to be between %d and %d\n\n",min,max);
}else if(option < min || option > max){
printf("\tThe option has to be between %d and %d\n\n",min,max);
}else{
break;
}
}while(1);
return option;
}
void showMenu(char *question, char **options, menu *actions, int length) {
int choose = 0;
int repeat = 1;
int i;
menu act;
do {
printf("\n\t %s \n", question);
for(i = 0; i < length; i++) {
printf("%d. %s\n", (i+1), options[i]);
}
choose = chooseOption(1,length);
printf(" \n");
act = actions[choose - 1];
repeat = act();
if(choose == 3){
repeat = 0;
}
}while(repeat == 1);
}
int installVLC(void) {
clearScreen(100);
char *question = "Installing VLC from:";
char *options[10] = {"PPA", "Source", "Back to VLC menu"};
menu actions[3] = {installVlcFromPpa, installVlcFromSource, mainMenu};
showMenu(question, options, actions, 3);
return 1;
}
int meniuVLC(void) {
clearScreen(100);
char *question = "VLC Options";
char *options[10] = {"Install VLC.", "Uninstall VLC.", "Back to Menu."};
menu actions[3] = {installVLC, uninstallVLC, mainMenu};
showMenu(question, options, actions, 3);
return 1;
}
void startMenu(void){
clearScreen(100);
char *question = "Choose a Menu:";
char *options[10] = {"Update system.", "Install VLC", "Quit"};
menu actions[3] = {updateSystem, meniuVLC, exitMenu};
showMenu(question, options, actions, 3);
}
int main(void){
startMenu();
return 0;
}
Choose a Menu:
1. Update system.
2. Install VLC
3. Quit
Choose an Option:
The most elegant way is to declare them as separate variables.
You can also use the first method but utilizing enums/defines, so that you have screens[MAIN_MENU][...] rather that some magic screens[0xcafebabe][...], it is equally acceptable.
I am a new C developer (I am used to programming in Java), and have tried create, what I thought was a simple bool function. Although I am getting an error which I don't understand how to fix:
#include <stdio.h>
#include <stdlib.h>
typedef enum { false, true } bool;
int main() {
int currentNumber, round = 1;
printf("Numbers generated will be between 1 and 20. \n");
currentNumber = rand() % 20;
bool validNumber = false;
do {
if(currentNumber != 0) {
validNumber == true;
} else {
currentNumber = rand() % 20;
}
}while(validNumber == false);
printf("You're on round" + ("%d", round));
printf("You're current number is: " + ("%d", currentNumber));
printf("Higher or Lower (H/L)?");
char userInput [20];
scanf("%s", &userInput);
if((userInput[0] == 'h') || (userInput[0] == 'H')) {
completeRound(round, 'H', currentNumber);
} else if((userInput[0] == 'l') || (userInput[0] == 'L')) {
completeRound(round, 'L', currentNumber);
}
}
void completeRound(int round, char input, int currentNumber) {
int initialVal = currentNumber, newVal;
if(input == 'H') {
newVal = rand() % 20;
bool checkResult(initialVal, newVal, input);
} else {
newVal = rand() % 20;
bool checkResult(initialVal, newVal, input);
}
}
bool checkResult(int initialVal, int finalVal, char input);
bool checkResult(int initialVal, int finalVal, char input) {
if(input == 'H') {
if(initialVal <= finalVal) {
return true;
} else {
return false;
}
}
if(input == 'L') {
if(initialVal >= finalVal) {
return true;
}else {
return false;
}
}
printf("An error has occurred! Aborting game...");
return false;
}
The error is as follows:
\main.c|39|error: conflicting types for 'checkResult'
At first, I thought that for some reason, in C you could only pass certain data types as arguments to a bool method, although I can not find a straight answer to this on Google. Other than that; I can not understand what it means by "conflicting types" (this is the first time I've debugged a C program.
The function I have used to call checkResult is as follows:
Before calling the function you need to write its prototype also. By default compiler is considering it as return type of int but actually it is bool.
so write bool checkResult(int initialVal, int finalVal, char input) before calling checkResult.
You probably have a typo in your code. The line
bool checkResult(initialVal, newVal, temp);
implicitly creates a prototype for a bool function. The types of the arguments are omitted and default to int in C versions prior to C99. This declaration is in conflict with the actual declaration, whose third parameter is of type char.
You probably meant something like this:
bool okay = checkResult(initialVal, newVal, temp);
This defines a bool variable okay and initialises it with the result of the function call. (But note that this variable is local to the current scope, so in your example you'd lose the result immediately.)
It is legal in C to declare a function inside a function body, although it is not good practice. It is more usual to declare them in headers or at the beginning of the file.
As of C99, implicit function declarations are invalid. There also isn't a default argument or function return type of int. You might consider to enforce the C99 standard (eg with -std=c99in gcc) to avoid falling into the implicit-declaration trap.
You have called functions before declaring them.So is the error. Because by default the return type of a c function is "int".
Add
void completeRound(int , char , int );
and
bool checkResult(int , int , char);
after your typedef (better this way than declaring them in body of the calling function).
And since checkResult() is returning a value of type bool you better assign it to a variable of type bool like
bool okay = checkResult(initialVal, newVal, temp); this.
Please help me with a spellcheck program in C. The majority of the coding are complete (I think...). I'm really stuck because I'm not sure why the program wouldn't compile. Admittedly, I'm still an amateur coder, would you also provide a few suggestions on some of the bad coding habits that I have in the code? Thank you!
Error Message:
1>------ Build started: Project: project7, Configuration: Debug Win32 ------
1>Compiling...
1>project7.c
1>c:\users\x309\documents\visual studio 2008\projects\project7\project7\project7.c(16) : warning C4101: 'dictionaryWord' : unreferenced local variable
1>c:\users\x309\documents\visual studio 2008\projects\project7\project7\project7.c(77) : warning C4029: declared formal parameter list different from definition
1>c:\users\x309\documents\visual studio 2008\projects\project7\project7\project7.c(91) : warning C4013: 'strlen' undefined; assuming extern returning int
1>c:\users\x309\documents\visual studio 2008\projects\project7\project7\project7.c(96) : warning C4013: 'strncmp' undefined; assuming extern returning int
1>c:\users\x309\documents\visual studio 2008\projects\project7\project7\project7.c(101) : warning C4013: 'printf' undefined; assuming extern returning int
1>c:\users\x309\documents\visual studio 2008\projects\project7\project7\project7.c(78) : warning C4101: 'i' : unreferenced local variable
1>Linking...
1>project7.obj : error LNK2019: unresolved external symbol _artLength referenced in function _spellCheck
1>C:\Users\x309\Documents\Visual Studio 2008\Projects\project7\Debug\project7.exe : fatal error LNK1120: 1 unresolved externals
1>Build log was saved at "file://c:\Users\x309\Documents\Visual Studio 2008\Projects\project7\project7\Debug\BuildLog.htm"
1>project7 - 2 error(s), 6 warning(s)
What's required...
There is only one stage on this project, writing the spellCheck routine. The spellCheck function has two parameters. The first parameter (article[]) is a pointer to an array of characters. The contents of this array are an article that you need to spell check. The end of the article is marked with the normal 0 (marking the end of a string). The article includes punctuation, upper and lower case words, numbers, and abbreviations. Your function must print every word in the article that cannot be found in the dictionary. The dictionary is the second parameter to the function (more on this later).
#include <stdio.h>
#include<string.h>
char dictionary[1000000];
char article[100000];
void spellCheck(char[], char[]);
int isLetter(char c);
void removePunc(char article[]);
void toLower( char article[]);
void lowerDictionary( char dictionary[]);
int artLength( char article[]);
void nextArticleWord(char article[], char articleWord[], int artLength, char dictionary[]);
int main(void) {
FILE* dict_file;
FILE* article_file;
int bytes_read;
char* p;
dict_file = fopen("american-english.txt", "r");
if (dict_file == 0) {
printf("unable to open dictionary file \"american-english.txt\"\n");
return -1;
}
article_file = fopen("article.txt", "r");
if (article_file == 0) {
printf("unable to open file \"article.txt\"\n");
return -1;
}
/* read dictionary */
p = dictionary;
p = fgets(p, 100, dict_file);
while (p != 0) {
while (*p != '\0') {
p += 1;
}
p = fgets(p, 100, dict_file);
}
/* read article */
p = article;
bytes_read = fread(p, 1, 1000, article_file);
p += bytes_read;
while (bytes_read != 0) {
bytes_read = fread(p, 1, 1000, article_file);
p += bytes_read;
}
*p = 0;
spellCheck(article, dictionary);
}
int articlePosition =0;
int dictionaryPosition = 0;
void spellCheck(char article[], char dictionary[]) {
char articleWord[50];
char dictionaryWord[50];
int articleLength = artLength(article);
removePunc(article);
toLower(article);
lowerDictionary(dictionary);
nextArticleWord(article, articleWord, articleLength, dictionary);
}
void nextDictionaryWord(char dictionary[], char dictionaryWord[]){
int i;
for(i =0; dictionary[dictionaryPosition] != '\n'; i++){
dictionaryWord[i] = dictionary[dictionaryPosition];
dictionaryPosition++;
}
}
int isLetter(char c){
if ( (c>='a'&&c<='z') || (c>='A'&&c<='Z'))
return 1;
return 0;
}
void removePunc(char article[]){
int i, j=0;
for ( i =0; article[i] != 0; i++){
if (isLetter(article[i])){
article[j] = article[i];
j++;
}
else if (!isLetter(article[i])){
article[j] = ' ';
j++;
}
}
}
void toLower( char article[]){
int i=0;
for( i; article[i] != 0; i++){
if ( article[i] >= 'A' && article[i] <='Z')
article[i] = article[i] + 32;
}
}
void lowerDictionary( char dictionary[]){
int i=0;
for(i; dictionary[i] != 0; i++){
if (dictionary[i] >= 'A' && dictionary[i] <= 'Z'){
dictionary[i] = dictionary[i] + 32;
}
}
}
int articleLength( char article[] ){
int count=0;
while (article[count] != 0)
count++;
return count;
}
void nextArticleWord(char article[], char articleWord[], int articleLength, char dictionaryWord[], char dictionary[]){
int j, i;
check:
while(!isLetter(article[articlePosition])){
if (article[articlePosition] == 0){
return;
}
articlePosition++;
}
for(j=0; article[articlePosition] != ' ' || articlePosition == articleLength; j++){
articleWord[j] = article[articlePosition];
articlePosition++;
}
if (strlen(articleWord)<2){
goto check;
}
articleWord[j+1] = 0;
//dictionary search
while (!strncmp(articleWord, dictionaryWord,strlen(articleWord))){
nextDictionaryWord(dictionary, dictionaryWord);
}
if(strncmp(articleWord, dictionaryWord,strlen(articleWord)))
return;
printf(articleWord);
}
You have made a forward declaration:
int artLength( char article[]);
but your actual implementation is:
int articleLength( char article[]);
Make them identical (change either one of them) and your project will compile.
Not much information to go on - in future you need to post the actual error messages you are getting. However, you definitely need to move your function declarations so they appear in the code before the main() function.
Have you tried going through the compiler errors and understanding what they mean?
From a cursory glance, here's where I think the problem is. The compiler error is:
error LNK2019: unresolved external symbol _artLength referenced in function _spellCheck
Which basically means the compiler is looking for a function called artLength, called from function spellCheck. However, it's not finding it.
It seems like you have a function called articleLength, which may be what you meant to write?
I would definitely advise you, however, to go over all the other output from your compiler and try to understand what it means. A lot of it is basically telling you that the compiler can't find certain functions, which is because you're calling them before you actually write them.
Dan's answer is absolutely fine, but the program still wont compile. In spellCheck function you haven't passed dictionaryWord[50] so it would shows you ("too few arguments passed") error as soon as you correct the error Dan pointed out and try to compile it.
This is for those who are viewing this question and trying to implement the spell checker in C:D