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'm writing a program that will simulate a randomized race between runners who are climbing up a mountain where dwarf orcs (dorcs) are coming down the mountain to attack the runners. It begins with two runners named harold and timmy at the bottom of the mountain. The runners make their way up the mountain in randomized moves where they may make progress forward up the mountain, or they may slide back down the mountain. Dorcs are randomly generated, and they inflict damage on a runner if they collide. The simulation ends when one of the runners reaches the top of the mountain, or when both runners are dead.
I'm struggling with a part where I have to implement the actual race loop. Once the race is initialized, the race loop will iterate until the race is over. This happens when either a winner has been declared, or when all runners are dead.
Every iteration of the race loop will do the following:
with 30% probability, dynamically allocate a new dorc as an EntityType structure, and initialize it as follows:
(a) a dorc’s avatar is always “d”
(b) each dorc begins the race at the top of the mountain, which is at row 2
(c) with equal probability, the dorc may be placed either in the same column as timmy, or in the same column as the harold, or in the column exactly half-way between the two
(d) add the new dorc to the race’s array of dorcs
(e) using the pthread_create() function, create a thread for the new dorc, and save the thread pointer in the dorc’s entity structure; the function that each dorc thread will execute is the void* goDorc(void*) function that you will implement in a later step; the parameter to the goDorc() function will be the EntityType pointer that corresponds to that dorc
I guess I'm confused with the logic of how to approach this. I decided to make a function called isOver() to indicate if the race is over, and then a separate function called addDorc() to initialize the Dorc elements and do all the requirements above.
In isOver(), I attempt to add a dorc object to the dorcs array by doing addDorc(race); with every iteration of the race loop/if the race hasn't ended or no one died. But I keep getting the error:
control.c:82:3: error: too few arguments to function ‘addDorc’
addDorc(race);
The problem is I don't think I can manually declare all the parameters in addDorc() because some elements like the "path" argument are based on probability. As mentioned above, with equal probability, the dorc may be placed either in the same column as timmy, or in the same column as the harold, or in the column exactly half-way between the two. The issue is I don't know how to factor this random value when calling addDorc() and would appreciate some help. I also don't know if I'm doing the "with 30% probability, dynamically allocate a new dorc as an EntityType structure" correctly and would be grateful for some input on that as well.
defs.h
typedef struct {
pthread_t thr;
char avatar[MAX_STR];
int currPos;
int path;
} EntityType;
typedef struct {
EntityType ent;
char name[MAX_STR];
int health;
int dead;
} RunnerType;
typedef struct {
int numRunners;
RunnerType *runners[MAX_RUNNERS];
int numDorcs;
EntityType *dorcs[MAX_DORCS];
char winner[MAX_STR];
int statusRow;
sem_t mutex;
} RaceInfoType;
void launch();
int addDorc(RaceInfoType*, char*, int, int);
int isOver(RaceInfoType*);
void initRunners(RaceInfoType*);
int addRunner(RaceInfoType*, char*, char*, int, int, int, int);
int randm(int);
void *goRunner(void*);
void *goDorc(void*);
RaceInfoType *race;
control.c
void launch(){
race = malloc(sizeof(RaceInfoType));
race->numRunners = 0;
initRunners(race);
if (sem_init(&race->mutex, 0, 1) < 0) {
printf("semaphore initialization error\n");
exit(1);
}
strcpy(race->winner, " ");
srand((unsigned)time(NULL));
int i;
for(i = 0; i < race->numRunners; ++i){
pthread_create(&(race->runners[i]->ent.thr), NULL, goRunner, " ");
}
race->numDorcs = 0;
}
int addDorc(RaceInfoType* race, char *avatar, int path, int currPos){
if(race->numDorcs == MAX_DORCS){
printf("Error: Maximum dorcs already reached. \n");
return 0;
}
race->dorcs[race->numDorcs] = malloc(sizeof(EntityType));
int timmysColumn = race->dorcs[race->numDorcs]->currPos;
int haroldsColumn = race->dorcs[race->numDorcs]->currPos;
int halfwayColumn = (timmysColumn+haroldsColumn)/2;
int r = rand()%100;
pthread_t dorc;
if(r <= 30){
strcpy(race->dorcs[race->numDorcs]->avatar, "d");
race->dorcs[race->numDorcs]->currPos = 2;
if(r <= 33){
race->dorcs[race->numDorcs]->path = timmysColumn;
}else if(r <= 66){
race->dorcs[race->numDorcs]->path = haroldsColumn;
}else{
race->dorcs[race->numDorcs]->path = halfwayColumn;
}
pthread_create(&dorc, NULL, goDorc, " ");
}
race->numRunners++;
}
int isOver(RaceInfoType* race){
int i;
for(i = 0; i < race->numRunners; ++i){
if((race->winner != " ") || (race->runners[race->numRunners]->dead = 1)){
return 1;
}
addDorc(race);
return 0;
}
}
void initRunners(RaceInfoType* r){
addRunner(r, "Timmy", "T", 10, 35, 50, 0);
addRunner(r, "Harold", "H", 14, 35, 50, 0);
}
int addRunner(RaceInfoType* race, char *name, char *avatar, int path, int currPos, int health, int dead){
if(race->numRunners == MAX_RUNNERS){
printf("Error: Maximum runners already reached. \n");
return 0;
}
race->runners[race->numRunners] = malloc(sizeof(RunnerType));
strcpy(race->runners[race->numRunners]->name, name);
strcpy(race->runners[race->numRunners]->ent.avatar, avatar);
race->runners[race->numRunners]->ent.path = path;
race->runners[race->numRunners]->ent.currPos = currPos;
race->runners[race->numRunners]->health = health;
race->runners[race->numRunners]->dead = dead;
race->numRunners++;
return 1;
}
Caveat: Because there's so much missing [unwritten] code, this isn't a complete solution.
But, I notice at least two bugs: the isOver bugs in my top comments. And, incrementing race->numRunners in addDorc.
isOver also has the return 0; misplaced [inside the loop]. That should go as the last statement in the function. If you had compiled with -Wall [which you should always do], that should have been flagged by the compiler (e.g. control reaches end of non-void function)
From that, only one "dorc" would get created (for the first eligible runner). That may be what you want, but [AFAICT] you want to try to create more dorcs (one more for each valid runner).
Also, the bug the compiler flagged is because you're calling addDorc(race); but addDorc takes more arguments.
It's very difficult to follow the code when you're doing (e.g.) race->dorcs[race->numDorcs]->whatever everywhere.
Better to do (e.g.):
EntityType *ent = &race->dorcs[race->numDorcs];
ent->whatever = ...;
Further, it's likely that your thread functions would like a pointer to their [respective] control structs (vs. just passing " ").
Anyway, I've refactored your code to incorporate these changes. I've only tried to fix the obvious/glaring bugs from simple code inspection, but I've not tried to recompile or address the correctness of your logic.
So, there's still more work to do, but the simplifications may help a bit.
void
launch(void)
{
race = malloc(sizeof(RaceInfoType));
race->numRunners = 0;
initRunners(race);
if (sem_init(&race->mutex,0,1) < 0) {
printf("semaphore initialization error\n");
exit(1);
}
strcpy(race->winner," ");
srand((unsigned)time(NULL));
int i;
for (i = 0; i < race->numRunners; ++i) {
RunnerType *run = &race->runners[i];
EntityType *ent = &run->ent;
pthread_create(&ent->thr,NULL,goRunner,ent);
}
race->numDorcs = 0;
}
int
addDorc(RaceInfoType* race,char *avatar,int path,int currPos)
{
if (race->numDorcs == MAX_DORCS) {
printf("Error: Maximum dorcs already reached. \n");
return 0;
}
EntityType *ent = malloc(sizeof(*ent));
race->dorcs[race->numDorcs] = ent;
int timmysColumn = ent->currPos;
int haroldsColumn = ent->currPos;
int halfwayColumn = (timmysColumn + haroldsColumn) / 2;
int r = rand()%100;
#if 0
pthread_t dorc;
#endif
if (r <= 30) {
strcpy(ent->avatar,"d");
ent->currPos = 2;
if (r <= 33) {
ent->path = timmysColumn;
} else if (r <= 66) {
ent->path = haroldsColumn;
} else {
ent->path = halfwayColumn;
}
pthread_create(&ent->thr,NULL,goDorc,ent);
}
#if 0
race->numRunners++;
#else
race->numDorcs += 1;
#endif
}
int
isOver(RaceInfoType* race)
{
int i;
for (i = 0; i < race->numRunners; ++i) {
#if 0
if ((race->winner != " ") ||
(race->runners[race->numRunners]->dead = 1))
return 1;
#else
RunnerType *run = &race->runners[i];
if ((race->winner != " ") || (run->dead == 1))
return 1;
#endif
addDorc(race);
#if 0
return 0;
#endif
}
#if 1
return 0;
#endif
}
void
initRunners(RaceInfoType* r)
{
addRunner(r,"Timmy","T",10,35,50,0);
addRunner(r,"Harold","H",14,35,50,0);
}
int
addRunner(RaceInfoType* race,char *name,char *avatar,int path,int currPos,
int health,int dead)
{
if (race->numRunners == MAX_RUNNERS) {
printf("Error: Maximum runners already reached. \n");
return 0;
}
RunnerType *run = malloc(sizeof(*run));
race->runners[race->numRunners] = run;
strcpy(run->name,name);
EntityType *ent = &run->ent;
strcpy(ent->avatar,avatar);
ent->path = path;
ent->currPos = currPos;
run->health = health;
run->dead = dead;
race->numRunners++;
return 1;
}
UPDATE:
I noticed in addDorc(), you put pthread_t dorc; in an if statement. I don't quite understand what my if statement is actually supposed to be checking though.
I forgot to mention/explain. I wrapped your/old code and my/new code with preprocessor conditionals (e.g.):
#if 0
// old code
#else
// new code
#endif
After the cpp stage, the compiler will only see the // new code stuff. Doing this was an instructional tool to show [where possible] what code you had vs what I replaced it with. This was done to show the changes vs. just rewriting completely.
If we never defined NEVERWAS with a #define NEVERWAS, then the above block would be equivalent to:
#ifdef NEVERWAS
// old code ...
#else
// new code
#endif
Would it still be under the if(r <= 30) part like I did in my original code?
Yes, hopefully now, it is more clear. #if is a cpp directive to include/exclude code (as if you had edited that way). But, a "real" if is an actual executable statement that is evaluated at runtime [as it was before], so no change needed.
My other concern is it doesn't look like dorc is used anywhere in the function because you write pthread_create(&ent->thr,NULL,goDorc,ent); which seems to use ent instead?
That is correct. It is not used/defined and the value goes to ent->thr. As you had it, the pthread_t value set by pthread_create would be lost [when dorc goes out of scope]. So, unless it's saved somewhere semi-permanent (e.g. in ent->thr), there would be no way to do a pthread_join call later.
The output of the program generates random results for a 100 rounds of 100 coin tosses. I need to get all of those H & T results (10,000) into SQLite for analysis.
Round 1:
TTTTTHHTHTTHHTTTHHTTTTTTTHHTTHHHHHHTTTHTHTTHHTTTHHHHHHTHTTTTHTHHTHTTTHTHTHTHTTHHTTTTTTHTHTTHHTTTTHTH
-
Round 99:
TTHHHTHTHHTTTHHTTHTHTHTTHHHHHTHTTTTHHHHTHTHTHTHHHHTTTTTHTTHHHTTTTHTTHHHHTTTTTTHHTHTTHTTTTHTHHTTHHTHT
Round 100:
THTHTHHHHHTTHTTTTTTTTTTTHTTHHTHHHTHHTHHHHTTHTHHTTHTHTHHTTHHHTHTHHTHTTTTTHTHTTHHTHTHHHTHTHHTHTHHTTTHH
I have little knowledge how to do this, so I looked into what others have done. Apparently Multi-row INSERT is not supported. Some sources say the only way to insert several rows in a batch is use a Select statement. How would I achieve this?
Assuming the database and table is already created, what code could I use in a C program to insert all this data into SQLite?
/* This file was mechanically generated from tests/check-pcg32.c */
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <time.h>
#include <string.h>
#include "pcg_basic.h"
int main(int argc, char** argv)
{
// Read command-line options
int rounds = 1000;
bool nondeterministic_seed = false;
int round, i;
++argv;
--argc;
if (argc > 0 && strcmp(argv[0], "-r") == 0) {
nondeterministic_seed = true;
++argv;
--argc;
}
if (argc > 0) {
rounds = atoi(argv[0]);
}
// In this version of the code, we'll use a local rng, rather than the
// global one.
pcg32_random_t rng;
// You should *always* seed the RNG. The usual time to do it is the
// point in time when you create RNG (typically at the beginning of the
// program).
//
// pcg32_srandom_r takes two 64-bit constants (the initial state, and the
// rng sequence selector; rngs with different sequence selectors will
// *never* have random sequences that coincide, at all) - the code below
// shows three possible ways to do so.
if (nondeterministic_seed) {
// Seed with external entropy -- the time and some program addresses
// (which will actually be somewhat random on most modern systems).
// A better solution, entropy_getbytes, using /dev/random, is provided
// in the full library.
pcg32_srandom_r(&rng, time(NULL) ^ (intptr_t)&printf,
(intptr_t)&rounds);
} else {
// Seed with a fixed constant
pcg32_srandom_r(&rng, 42u, 54u);
}
printf("pcg32_random_r:\n"
" - result: 32-bit unsigned int (uint32_t)\n"
" - period: 2^64 (* 2^63 streams)\n"
" - state type: pcg32_random_t (%zu bytes)\n"
" - output func: XSH-RR\n"
"\n",
sizeof(pcg32_random_t));
for (round = 1; round <= rounds; ++round) {
printf("Round %d:\n", round);
/* Make some 32-bit numbers */
printf(" 32bit:");
for (i = 0; i < 6; ++i)
printf(" 0x%08x", pcg32_random_r(&rng));
printf("\n");
/* Toss some coins */
printf(" Coins: ");
for (i = 0; i < 100; ++i)
printf("%c", pcg32_boundedrand_r(&rng, 2) ? 'H' : 'T');
printf("\n");
printf("\n");
}
return 0;
}
I guess I would start with a simple approach and if you need to access results based on rounds and tosses, your table in the database could consist of three fields, e.g. round, toss and result.
To create the database and the table, you could use the command line program sqlite3 as follows:
sqlite3 random.sqlite
Then enter the following command at the command prompt:
CREATE TABLE experiment (round INT, toss INT, result CHAR(1));
Now you have created a database random.sqlite and a table experiment.
How to fill this table from C?
One way would be:
open db
create a prepared insert statement
start a transaction
in a loop:
bind values to parameters
run the SQL
reset prepared statement
end transaction
finalize the statement and close the db to avoid resource leaks
A simple example of the flow described could look like this:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sqlite3.h"
void exit_with_error(sqlite3 *db, const char * msg) {
fprintf(stderr, "%s: %s\n", msg, sqlite3_errmsg(db));
sqlite3_close(db);
exit(1);
}
char *pathToDB = "<a path to random.sqlite>";
sqlite3 *open_db(void);
sqlite3_stmt *prepeare_stmt(sqlite3 *db);
void close_db(sqlite3 *db, sqlite3_stmt *stmt);
int main() {
sqlite3 *db = open_db();
sqlite3_stmt *stmt = prepeare_stmt(db);
if(sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, NULL) != SQLITE_OK) {
exit_with_error(db, "begin transaction failed");
}
char *result = "H";
for(int round = 0; round < 100; round++) {
for(int toss = 0; toss < 100; toss++) {
//for a short test simply output alternately "H" and "T"
result = strcmp(result, "H") == 0 ? "T" : "H";
//bind values to parameters
sqlite3_bind_int(stmt, 1, round);
sqlite3_bind_int(stmt, 2, toss);
sqlite3_bind_text(stmt, 3, result, -1, SQLITE_STATIC);
//run the SQL
if (sqlite3_step(stmt) != SQLITE_DONE) {
exit_with_error(db, "insert failed");
}
//reset prepared statement to be able to bind new values in next loop pass
if (sqlite3_reset(stmt) != SQLITE_OK) {
exit_with_error(db, "reset failed");
}
}
}
if(sqlite3_exec(db, "END TRANSACTION", NULL, NULL, NULL) != SQLITE_OK) {
exit_with_error(db, "end transaction failed");
}
//finalize the stmt and close db to avoid resource leaks
sqlite3_finalize(stmt);
sqlite3_close(db);
return 0;
}
sqlite3 *open_db(void) {
sqlite3 *db;
if (sqlite3_open(pathToDB, &db) != SQLITE_OK) {
exit_with_error(db, "can't open db: ");
}
return db;
}
sqlite3_stmt *prepeare_stmt(sqlite3 *db) {
sqlite3_stmt *stmt;
//create a prepared statement
int rc = sqlite3_prepare_v2(db, "INSERT INTO experiment VALUES (?1,?2,?3)", -1, &stmt, 0);
if (rc != SQLITE_OK) {
exit_with_error(db, "failure preparing insert");
}
return stmt;
}
Note: Instead of using random values, the code simply outputs 'T' and 'H' alternately to have a simple test case.
After executing the program, you can take a look at the stored values with the command line as follows:
sqlite3 random.sqlite
At the sqlite command prompt you can enter:
SELECT * FROM experiment;
The following should then be output in the console:
0|0|T
0|1|H
0|2|T
...
99|97|H
99|98|T
99|99|H
To get the value for the third toss in the first round you would issue the following sql statement from the command prompt:
SELECT * from experiment WHERE round=0 and toss=2;
that would output something like this on the console:
0|2|T
Is it possible to replace all of these "if, else if ..." with an array of function pointers in this example of code ?
if (strncmp(buff, "ls\n", 3) == 0)
my_ls();
else if (strncmp(buff, "cd\n", 3) == 0)
my_cd();
else if (strncmp(buff, "user\n", 5) == 0)
my_user();
else if (strncmp(buff, "pwd\n", 4) == 0)
my_pwd();
else if (strncmp(buff, "quit\n", 5) == 0)
my_quit();
I'm trying to get something like this :
void (*tab[5]) (void);
tab[0] = &my_ls;
tab[1] = &my_cd;
tab[2] = &my_user;
tab[3] = &my_pwd;
tab[4] = &my_quit;
I created a code to illustrate what you wanted to do, because I it's pretty entertaining.
#include <stdio.h>
#include <string.h>
// your functions
void my_ls() { puts("fun:my_ls") ;}
void my_cd() { puts("fun:my_cd") ;}
void my_user(){ puts("fun:my_user");}
void my_pwd() { puts("fun:my_pwd") ;}
void my_quit(){ puts("fun:my_quit");}
int main(int argc, char const *argv[])
{
char* buff="ls\n"; // the string you have to compare
void (*tab[5]) (void)={my_ls,my_cd,my_user,my_pwd,my_quit};
char *names[5]={"ls\n","cd\n","user\n","pwd\n","quit\n"};
int i;
for (i=0; i<5; i++)
{
if(strncmp(buff,names[i],strlen(names[i]) )==0){
tab[i]();
return 0;
}
}
return 0;
}
There are other ways to write it. Actually my_function is the same as &my_function since a function name alone is converted to the adress of the function.
Also tab[i]() is equivalent to (*tab[i])()... Those are weird behaviours but I think it's specified by C standard
There's no problem with an array of function pointers, but you'd need to convert the sequence of boolean strncmp() results to a single index.
If the list is long, the hash table idea might be a winner. For compact, simple code and easy maintenance, I've used an array of structs:
typedef struct cmdtable_t
{
void (*fptr)();
unsigned char length
char name[11];
} cmdtable_t, *pcmdtable_t;
cmd_table_t commands = {
{ my_ls, 2, "ls"},
{ my_cd, 2, "cd" },
{ my_user, 4, "user" },
...etc.
};
That could also be what a hash table entry looks like, could be sorted in advance to allow a binary search, or simply sequentially searched for a KISS version until you find out whether this needs optimizing at all.
I think you want a dictionary or hashtable:
Use buff as string key
Use function pointer as values
The following line has the problem int (*f)(int, int) = (argv[2][0] == 'd') , on compiling it says declaration not allowed here . Should the line be declared at the start , any better way of doing this .Any suggestions would be greatly appreciated?
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int encode(int ch, int key) {
if (islower(ch)) {
ch = (ch-'a' + key) % 26 + 'a';
ch += (ch < 'a') ? 26 : 0;
}
else if (isupper(ch)) {
ch = (ch-'A' + key) % 26 + 'A';
ch += (ch < 'A') ? 26 : 0;
}
return ch;
}
int decode(int ch, int key) {
return encode(ch, -key);
}
int main(int argc, char **argv) {
int ch;
int key;
if (argc < 2) {
printf("USAGE: cipher <integer key> <encode | decode>\n");
printf("Then, just type your text and it will automatically output the en/de crypted text! :)\n");
return 1;
}
key = atoi(argv[1]);
if (key < 1 || key > 25) {
printf("Key is invalid, or out of range. Valid keys are integers 1 through 25.\n");
return 1;
}
int (*f)(int, int) = (argv[2][0] == 'd') ?
decode :
encode;
while (EOF != (ch=getchar()))
putchar(f(ch, key));
return 0;
}
In C (prior to C99), you have to declare variables at the start of a block.
Either compile your code as C99, or change the code so that f is declared at the start of a block.
In c89/90 You must declare all the variables in the starting of the block
But In c99 , You can compile your code with -std=c99 like this:
gcc -Wall -std=c99 test.c -o test.out
Other than the part pointed out by NPE, you can use typedef to create a Function Type. like this:
typedef void FunctionType (int, int); And then use it(as a separate type) to create function pointers.
Makes reading easy.
Should the line be declared at the start
In C89 definitions must occur before any statements in the block. If you do move it, you don't have to move the whole line (and of course you don't want to move the whole line to before the code that checks argv[2] is valid). Just move the definition of f:
int ch;
int key;
int (*f)(int,int);
...
f = (argv[2][0] == 'd') ? decode : encode;
any better way of doing this
It's not necessarily better in this case, but note that the rule is the start of a block, not necessarily the start of a function.
So, you could just write:
{
int (*f)(int, int) = (argv[2][0] == 'd') ?
decode :
encode;
while (EOF != (ch=getchar()))
putchar(f(ch, key));
}
return 0;
You can easily get into arguments about this coding style. Some people think every function should define all its variables up front, and that introducing a block just to define a variable is cluttered and/or confusing. Some people (and especially those who use C++ as well as C) think you should restrict the scope of each variable to as narrow a piece of code as possible, that that defining everything at the start of the function is cluttered and/or confusing. But even they might consider a bare block excessive.