Edit: I made some changes at my code.
I want to write a line fitting program by using the data from two .txt file. The code is as following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int data_read(char programs_x[], char programs_y[]) {
int i=0, j=0, k;
int numProgs_x=0;
int numProgs_y=0;
char line_x[1024];
char line_y[1024];
FILE *file_x;
FILE *file_y;
file_x = fopen("data_x.txt", "r");
file_y = fopen("data_y.txt", "r");
while(fgets(line_x, sizeof line_x, file_x)!=NULL) {
//check to be sure reading correctly
//printf("%s", line_x);
//add each filename into array of programs
programs_x[i]=strdup(line_x);
i++;
//count number of programs in file
numProgs_x++;
}
while(fgets(line_y, sizeof line_y, file_y)!=NULL) {
//check to be sure reading correctly
//printf("%s", line_y);
//add each filename into array of programs
programs_y[j]=strdup(line_y);
j++;
//count number of programs in file
numProgs_y++;
}
fclose(file_x);
fclose(file_y);
return 0;
}
int main ( void ) {
int i, j, k, n=1024;
float s1=0,s2=0,s3=0,s4=0,a,d,b;
char programs_x[1024], programs_y[1024];
data_read(programs_x, programs_y);
for(i=0;i<n;i++) {
scanf("%f", &programs_x[k]);
}
for(i=0; i<n; i++){
scanf("%f", &programs_y[k]);
}
for(i=0;i<n;i++) {
s1=s1+programs_x[i];
s2=s2+programs_x[i] * programs_x[i];
s3=s3+programs_y[i];
s4=s4+programs_x[i] * programs_y[i];
}
d=n*s2-s1*s1;
a=(s2*s3-s1*s4)/d;
b=(n*s4-s1*s3)/d;
printf("\nThe values of a and b are : %f\t%f\n",a,b);
printf("\nThe Required Linear Relation is : \n");
if(b>0){
printf("\ny=%f+%fx\n",a,b);
}
else {
printf("y=%f%fx",a,b);
}
return 0;
}
When I try to compile this code, the compiler shows these error:
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
test3.c:
Error E2349 test3.c 22: Nonportable pointer conversion in function data_read
Error E2349 test3.c 33: Nonportable pointer conversion in function data_read
*** 2 errors in Compile ***
How do I fix the errors? Where did I make mistakes in declaring and calling the data types? I'm pretty sure I declare programs_x and programs_y as char this time and not int.
The error is difficulty to pin down as we don't have line numbers but this line is definitely not right in your main:
data_read(char programs_x[], char programs_y[]);
To call a function you just list the variables and values you're passing to it like this:
data_read(programs_x, programs_y);
Which will no doubt cause more errors/warnings to be flagged as you declare programs_x and programs_y as arrays of int, but data_read is expecting arrays of char. So there's a conflict in what you think your function wants and what you're providing to it which you need to sort out.
The error could mean that the non-standard function strdup() is not supported. A C compiler does not need to support it, which is why it is a good idea to avoid that function. If the function is supported as a non-standard extension (it is part of POSIX), you might find it in the header <string.h> which you didn't include.
As for the cause of the rest of the errors, I have no idea, since those appear to originate from other files than the one you posted.
Related
Consider the following C program:
#include <stdio.h>
const int OP_0 = 0;
const int OP_1 = 1;
const int OP_2 = 2;
int op_0(int x) {
return x + 2;
}
int op_1(int x) {
return x * 3 + 1;
}
int op_2(int x) {
return 2 * x * x - 10 * x + 5;
}
int compute(int op, int x) {
switch (op) {
case OP_0: return op_0(x);
case OP_1: return op_1(x);
case OP_2: return op_2(x);
}
return 0;
}
int main() {
int opcode;
int number;
printf("Enter the opcode: ");
scanf("%d", &opcode);
printf("Enter the number: ");
scanf("%d", &number);
printf("Result: %d\n", compute(opcode, number));
return 0;
}
It is a very simple program that lets the user select one of 3 operations to perform on an int input. To use this program, we can compile it with, for instance, gcc program.c -o program, and then run it with ./program. That's all obvious. Suppose, though, that we wanted to add another operation:
int op_3(int x) {
return 900 + x;
}
If we wanted to use this new operation, we'd need to recompile the entire program. Adding a new operation to this program has O(n) complexity, and is slow since it requires a complete recompilation.
My question is: is it possible, in C, to let this program add new native operations (without writing an interpreter)? In other words, is it possible to dynamically compile and add op_3 to the C program above, without having to recompile everything?
For illustration purposes, here is an example of what I have in mind:
int compute(int op, int x) {
// the first time it runs, would load `op_N.dll`
// the next time, would use the loaded version
// so, to add a new operation, we just compile
// it and add `op_N.dll` to this directory
Fun op = dynamic_load(op);
return op(x);
}
The only way I can think of is to compile a new dynamic library that is then opened by the program using dlopen()...
Another way, similar but perhaps more primitive, would be to compile the code into an object file and then load it into a mmaped region with execution permissions, jumping then to it using a function pointer.
To do this, compile the new function using gcc -c, clean the binary code from the headers with objcopy -O binary -j .text. Now in the program open() the resulting file and use the mmap() function to map this file in memory, giving as protections PROT_READ | PROT_EXEC. You'd look up the manuals for all this functions.
Note that I am assuming that you are on a unix system. I don't know much about Windows, but I imagine that something similar could be done with VirtualAlloc().
Well, what you are asking is the "Open Principle of SOLID". To do so, you need to have a dynamic dlsym obviously after dlopen. To have a dynamic dlsym you need to be able to read header files or a file with the proper function prototypes. Yes, you need to cast function pointers, but the typecast depends upon the types of your parameter list.
Edit:
Hard coding dlsym means you have to relink your import library to your executable every time you add a function to your shared object.
OR
You have two shared objects. One is the import library, and the other is the library that you want to add functionality. As David Wheeler said, "All problems of computer science could be solved with another level of indirection, except for the problem with too many layers of indirection.".
Complete noob-proof answer. As the other answers suggested, we can use dlopen and dlsym to dynamically load a shared library on C. First of all, let's create the lib. Save the following file as 0.c
int fn(int x) {
return x * 10;
}
Then, run the following command to create the shared lib:
clang -shared 0.c -o 0
Now, we must edit our compute function to load fn from 0.c dynamically and use it. First, we declare an fn : int -> int function pointer:
int (*fn)(int);
Then, we convert the operation to decimal (since we saved the shared lib as 0, no extension):
char file[256];
sprintf(file, "%d", 0);
Then, we load 0 dynamically:
void *handle = dlopen(file, RTLD_LAZY);
Then, we find fn on that lib, and assing to the fn function pointer:
*(void**)(&fn) = dlsym(LIB[op], "fn");
Then, we can just call it!
fn(5) // will return 50
Here is a complete example, that handles errors and stores the function pointers in a jump table (so we don't need to re-load the lib every time, obviously!):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
const int MAX_OPS = 256;
// Jump-table with available functions
int (*OP[MAX_OPS])(int);
// Array with shared libraries
void* LIB[MAX_OPS];
// Loads an operation dynamically
void load_op(int op) {
int (*fn)(int);
// Generates the file name
char file[256];
sprintf(file, "%d", op);
// Opens the dynamic lib
LIB[op] = dlopen(file, RTLD_LAZY);
// Handles error opening the lib
if (!LIB[op]) {
fprintf(stderr, "Couldn't load operation: %s\n", dlerror());
}
// Creates the function pointer
*(void**)(&fn) = dlsym(LIB[op], "fn");
// Handles error finding the function pointer
if (!fn) {
fprintf(stderr, "Couldn't load operation: %s\n", dlerror());
dlclose(LIB[op]);
}
// Adds to jump table
OP[op] = fn;
}
// Clears the dynlib objects
void close_ops() {
for (int op = 0; op < MAX_OPS; ++op) {
dlclose(LIB[op]);
}
}
// Applies the specified operation to an input
// Requires a shared object file with a name equivalent to the decimal
// representation of op to be loaded on the current directory
int compute(int op, int x) {
if (!OP[op]) {
load_op(op);
}
return OP[op](x);
}
int main() {
int opcode;
int number;
printf("Enter the opcode: ");
scanf("%d", &opcode);
printf("Enter the number: ");
scanf("%d", &number);
printf("Result: %d\n", compute(opcode, number));
return 0;
}
All the credit to the people who took their time to answer my question here and on #c on Libera.Chat. Thank you!
This question already has answers here:
How can I use an array of function pointers?
(12 answers)
Closed 4 years ago.
When I was making my terminal i was wondering if I can call a function by array.
(This code is not done yet so please code is a bit messy.)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <unistd.h>
#include <limits.h>
#define true 1
#define false 0
typedef int bool;
/* Static */
static char Input[CHAR_MAX];
static char CurrentDirectory[CHAR_MAX];
static char *Command;
static char *Argument;
static char *Commands[]={"test","test2"};
/* Functions */
int Check_Command();
int test();
int test2();
/* --------- */
int main(){
printf("#######################\n\tterminal\n\tType \"help\" for the list of commands\n#######################\n");
prompt:
printf(">");
fgets(Input,CHAR_MAX,stdin);
int res=Check_Command();
if(res==0){printf("Unknown Command!\n");}
goto prompt;
}
/* Check_Command() function returns 0 if doesn't suceed and returns 1 of it suceeds */
int Check_Command(){
//Since input variable is static, no need to send in arguments
Input[strcspn(Input,"\r\n")]=0;
Command=strtok(Input," ");
Argument=strtok(NULL," ");
int x=0;
while(x<sizeof(Commands)){
if(strcmp(Command,Commands[x])==0){
Commands[x](); <----- Can I call a function like this?
return 1;
}
x++;
}
return 0;
}
/* Commands */
int test(){
printf("Success!\n");
getchar();
exit(0);
}
int test2(){
print("Success [2] \n");
getchar();
exit(0);
}
If this possible then this would be lit, Im too lazy to make commands into a executable and using if statements for all commands.
if you are too lazy to read the whole code here is a basic concept (UNTESTED):
static *Commands[]={"test","test2"};
int main(){
char *Command="test";
int x=0;
while(x<sizeof(Commands)){
if(strcmp(Command,Commands)==0){
Commands[x]();
}
x++
}
}
int test(){
printf("Hi");
}
int test2(){
printf("hey");
}
Edit:
static char Commands[]={test,test2}; DOES NOT WORK
This also includes the "possible duplicate" answer. (Im using Mingw, Windows 10)
It appears that you want to be able to take in a string such as test2 from the user, and then invoke the function test2(). There are two main ways you can approach this:
Homebrew structure mapping names to function pointers.
Using 'dynamic library loading' and function name resolution.
Array of structures
For the first, you define a structure such as:
struct FuncName
{
const char *name;
int (*function)(void);
};
And you can then define an array of these:
struct FuncName functions[] =
{
{ "test", test },
{ "test2", test2 },
};
enum { NUM_FUNCTIONS = sizeof(functions) / sizeof(functions[0]) };
When you get a name from the user, you can search through the array of names and find the matching function pointer to call.
int invoke_function(const char *name)
{
for (int i = 0; i < NUM_FUNCTIONS; i++)
{
if (strcmp(name, functions[i].name) == 0)
{
return (*functions[i].function)();
// Or just: return functions[i].function();
}
}
return -1; // No match found
}
This works reliably on all systems, but the demerit is that you must create the table of function pointers when you compile the program.
Dynamic library
The alternative is to use functions dlopen() and dlsym() from the <dlsym.h> header on Unix (POSIX) systems, or the equivalent on Windows.
Normally, you expect to find the functions in dynamically loaded libraries loaded with dlopen(), but there's usually a way to search the main executable for the names instead (pass a null pointer as the file name to dlopen() on POSIX systems). You can then call dlsym() to get the function pointer corresponding to the name you specify, which you can call.
void *dlh = dlopen(NULL, RTLD_NOW);
int (*funcptr)(void) = (int (*)(void))dlsym("test", dlh);
return (*funcptr)();
This omits error checking and you need the cast to convert from an object pointer (void *) to a function pointer because the C standard does not require that to be doable, but POSIX does (see the specification of
dlsym() already linked to).
Non-uniform function signatures
With both solutions, life is easy if all the callable functions have the same interface. Life is much messier if the different functions have different interfaces (so some expect no arguments, some expect one, some expect two, and the types of the arguments vary between functions, as do the return types). Expect to use lots of casts and be prepared to bludgeon the compiler into submission — isolate the code from everything else so as to leave the non-portable part well separated from the main code.
Beware: no compiler was consulted about the validity of any of this code!
I'm new in programming and iam from Tver.
There is a problem in program. I don't know where. I am using input file and output file. So, i tried to debug program, but i failed
I'm using a Visual Studio 2010.
Thank you in advance.
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <conio.h>
#include <string.h>
using namespace std;
int num[100];
void outc(int s, int ss)
{int i,temp,numb[100],k,l,t;
temp=s; i=0;
while (temp>0)
{
numb[i]=temp%ss;
if (numb[i]>=10) numb[i]='A'-10+temp%16;
temp/=ss;
i++;}
l=i/2; t=0;
i--;
while (i>=l)
{
k=numb[t];
numb[t]=numb[i];
numb[i]=k;
t++;
i--;
}
FILE* fooo;
errno_t errorCodes=fopen_s(&fooo,"output.txt","w");
fprintf(fooo,"s%d= %d\n", ss, numb);
return;
}
int main()
{char c,strbuf[100],num[100];
char *res;
int k,s,i,temp,ost,s2,s8,s10,s16;
FILE* foo;
errno_t errorCode=fopen_s(&foo,"input.txt","r");
fgets(strbuf,1000,foo);
if(strbuf[strlen(strbuf)-1]=='b')
{
strncpy_s(strbuf, strbuf, strlen(strbuf)-1);
c=atoi(strbuf);
k=0;s=0;
while(c!=0)
s+=(c%10)*pow(2,k);
c/=10;
k++;
} else
if(strbuf[0]==0 && strbuf[1]!='x')
{i=0;;
do{
strbuf[i]=strbuf[i+1];
i++;
}while(i!=strlen(strbuf)-1);
c=atoi(strbuf);
k=0;s=0;
while(c!=0)
s+=(c%10)*pow(8,k);
c/=10;
k++;
} else
if(strbuf[0]=='0' && strbuf[1]=='x')
{i=0;k=strlen(strbuf);
do{
strbuf[i]=strbuf[i+2];
i++;
}while(i!=k);
puts(strbuf);
k=0;s=0;
for (i=strlen(strbuf)-1;i>=0; i--)
{
if (strbuf[i]>='A' && strbuf[i]<='F')
c=10+strbuf[i]-'A'; else c=strbuf[i]-'0';
printf("%d\n",c);
s+=c*pow(16,k);
k++;
}
} else s=atoi(strbuf);
printf("%d\n",s);
outc(s,2);
outc(s,8);
FILE* fooo;
errno_t errorCodep=fopen_s(&fooo,"output.txt","w");
fprintf(fooo,"s10= %d\n", s);
outc(s,16);
//if (temp%16>=10) num[len-1]='A'-10+temp%16;
//printf("s2= %d\ns8= %d\ns10= %d\ns16= %d\n", s2, s8, s, s16);
_getch();
return 0;
}
This has numerous issues:
You can't #include <iostream> or have using namespace std in a C program.
There are so many compiler specific things in here that it's going to be hard for most people to help you. You'll make your life a lot easier by writing in standard C. There's no way for me to compile this program to check what's wrong with it, for instance.
Your code is very hard to follow when you use variable names like k, and s, and s2, and the like, and do things like FILE * foo followed by FILE * fooo. Your code is also just formatted horribly.
With strncpy_s(strbuf, strbuf, ...) unless Microsoft is doing something really weird, here, you can't specify the same string as both the source and destination.
strtol() is better here than atoi().
You're not closing any of the files you open, and you're not checking whether they did, in fact, open. Using the & operator here: errorCode=fopen_s(&foo, ... is highly suspicious, but again, you're using some non-standard function, so who knows.
Here: fprintf(fooo,"s%d= %d\n", ss, numb) you tell fprintf() to expect two ints, but the last argument is an array.
Is there any reason that a program, which compiled earlier, should seg fault at a point because of fgets? I changed no code related to it AT ALL. Suddenly I believe it is failing to open the file, but I tested it with the file like fifteen minutes ago.... All I did was add a search function, so I don't understand what the issue is.....
Could it be the server I'm connecting to over PuTTy?
int createarray( int **arrayRef, FILE *fptr){
int size = 0, i;
char rawdata[100];
while (fgets(rawdata, 99, fptr) != NULL){
size++;
}
rewind(fptr);
*arrayRef = malloc(sizeof(int) * size);
for ( i = 0; i < size; i++ ){
fgets(rawdata, 99, fptr);
*(*arrayRef + i) = atoi(rawdata);
}
return size;
}
int main ( int argc, char **argv ) { //main call
// declare variable to hold file
FILE *inFilePtr = fopen(*(argv + 1), "r");
int **aryHold;
int numElements, sortchoice, key, foundindex;
// Call function to create array and return num elements
numElements = createarray(aryHold, inFilePtr);
This is the code that compiled, performed correct, and hasn't been changed since. GDB says there is an error with fgets.
OK, the reason it use to "work" is you were clobbering an unimportant memory location. Changing your code shifted things around and now you are clobbering something important.
You're passing an uninitialized pointer to createarray(). You wanted to do something like:
int* aryHold;
//...
... createarray(&aryHold ...
BTW, many compilers have the ability to catch this kind of error for you. If you haven't already, you might want to see if your compiler has an error checking option that could have saved you hassling with this (and perhaps find some other code that only "works" accidentally).
Here's my code. It works when I comment out the "luetut" variable.
But when I compile as follows, I get segmentation fault when the program should print the variables. What sense does this make? When I try to make a debug build, something totally weird shows up (multiple definition of this and that).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct rakenne
{
int luku;
float liukuluku;
char* mjono;
} Rakenne;
int main(int argc, char *argv[])
{
int luetut = 0;
Rakenne palikka;
// Rakenne palikka, *palikkaosoitin;
// palikkaosoitin = &palikka;
// while(luetut < 1)
// {
printf("Anna luku:\n");
scanf("%d", &palikka.luku);
// } luetut = 0;
// while(luetut < 1)
// {
printf("Anna liukuluku:\n");
scanf("%f", &palikka.liukuluku);
// } luetut = 0;
printf("Anna merkkijono:\n");
scanf("%s", palikka.mjono);
printf("%i\t%.3f\t%s\n", palikka.luku, palikka.liukuluku, palikka.mjono);
return 0;
}
So, is my gcc compiler broken or what could be the problem?
scanf("%s", palikka.mjono);
You didn't make mjono point to anything so writing to it is of course illegal - undefined behavior. Doing something like this leads to erratic behavior: the program "works" or "fails" for no apparent reason.
So, is my gcc compiler broken or what could be the problem
It's rarely constructive to think the tools you are using are the problem.
Expanding on cnicutars answer, the fix would be to allocate some memory for palikka.mjono.
Something like this:
#define SIZE 40 // or whatever you need.
palikka.mjono = malloc( sizeof(char) * SIZE );
Then later don't forget to free that memory:
free( palikka.mjono );
Or if you know what the maximum size of your strings will be, just define your structure as:
typedef struct rakenne
{
int luku;
float liukuluku;
char mjono[SIZE];
} Rakenne;