ssscanf unexpected behavior - c

When I use sscanf on url http://www.website.com:30081/text.txt, like this:
int parse_url(char *url, requesthdrs *hdrs, char
*uri, char *domain_name) {
int request_port;
int host_hdr_len;
char temp[MAXLINE];
size_t uri_len = 1;
/* case 1: request_port specified */
/* format: http://domain_name:request_port/... */
if(sscanf(url, "http://%s:%d%s", domain_name,
&request_port, uri) == 3) {
fprintf(stderr, "case1\n");
host_hdr_len = build_hosthdr(hdrs->host,
domain_name, request_port);
}
The program fails to enter case 1, why is that the case?

The %s reads until the first white space, or end of string. That isn't what you want or need. Use %[^:] (a scan set that matches anything except a colon)
instead.
Beware of buffer overflows. You don't know how big the strings can be.

Related

How to read imaginary data from text file, with C

I am unable to read imaginary data from text file.
Here is my .txt file
abc.txt
0.2e-3+0.3*I 0.1+0.1*I
0.3+0.1*I 0.1+0.4*I
I want to read this data into a matrix and print it.
I found the solutions using C++ here and here. I don't know how to do the same in C.
I am able to read decimal and integer data in .txt and print them.
I am also able to print imaginary data initialized at the declaration, using complex.h header. This is the program I have writtern
#include<stdio.h>
#include<stdlib.h>
#include<complex.h>
#include<math.h>
int M,N,i,j,k,l,p,q;
int b[2];
int main(void)
{
FILE* ptr = fopen("abc.txt", "r");
if (ptr == NULL) {
printf("no such file.");
return 0;
}
long double d=0.2e-3+0.3*I;
long double c=0.0000000600415046630252;
double matrixA[2][2];
for(i=0;i<2; i++)
for(j=0;j<2; j++)
fscanf(ptr,"%lf+i%lf\n", creal(&matrixA[i][j]), cimag(&matrixA[i][j]));
//fscanf(ptr, "%lf", &matrixA[i][j]) for reading non-imainary data, It worked.
for(i=0;i<2; i++)
for(j=0;j<2; j++)
printf("%f+i%f\n", creal(matrixA[i][j]), cimag(matrixA[i][j]));
//printf("%lf\n", matrixA[i][j]); for printing non-imainary data, It worked.
printf("%f+i%f\n", creal(d), cimag(d));
printf("%Lg\n",c);
fclose(ptr);
return 0;
}
But I want to read it from the text, because I have an array of larger size, which I can't initialize at declaration, because of it's size.
There are two main issues with your code:
You need to add complex to the variables that hold complex values.
scanf() needs pointers to objects to store scanned values in them. But creal() returns a value, copied from its argument's contents. It is neither a pointer, nor could you get the address of the corresponding part of the complex argument.
Therefore, you need to provide temporary objects to scanf() which receive the scanned values. After successfully scanning, these values are combined to a complex value and assigned to the indexed matrix cell.
Minor issues not contributing to the core problem are:
The given source is "augmented" with unneeded #includes, unused variables, global variables, and experiments with constants. I removed them all to see the real thing.
The specifier "%f" (as many others) lets scanf() skip whitespace like blanks, tabs, newlines, and so on. Providing a "\n" mostly does more harm than one would expect.
I kept the "*I" to check the correct format. However, an error will only be found on the next call of scanf(), when it cannot scan the next number.
You need to check the return value of scanf(), always! It returns the number of conversions that were successful.
It is a common and good habit to let the compiler calculate the number of elements in an array. Divide the total size by an element's size.
Oh, and sizeof is an operator, not a function.
It is also best to return symbolic values to the caller, instead of magic numbers. Fortunately, the standard library defines these EXIT_... macros.
The signs are correctly handled by scanf() already. There is no need to tell it more. But for a nice output with printf(), you use the "+" as a flag to always output a sign.
Since the sign is now placed directly before the number, I moved the multiplication by I (you can change it to lower case, if you want) to the back of the imaginary part. This also matches the input format.
Error output is done via stderr instead of stdout. For example, this enables you to redirect the standard output to a pipe or file, without missing potential errors. You can also redirect errors somewhere else. And it is a well-known and appreciated standard.
This is a possible solution:
#include <stdio.h>
#include <stdlib.h>
#include <complex.h>
int main(void)
{
FILE* ptr = fopen("abc.txt", "r");
if (ptr == NULL) {
perror("\"abc.txt\"");
return EXIT_FAILURE;
}
double complex matrixA[2][2];
for (size_t i = 0; i < sizeof matrixA / sizeof matrixA[0]; i++)
for (size_t j = 0; j < sizeof matrixA[0] / sizeof matrixA[0][0]; j++) {
double real;
double imag;
if (fscanf(ptr, "%lf%lf*I", &real, &imag) != 2) {
fclose(ptr);
fprintf(stderr, "Wrong input format\n");
return EXIT_FAILURE;
}
matrixA[i][j] = real + imag * I;
}
fclose(ptr);
for (size_t i = 0; i < sizeof matrixA / sizeof matrixA[0]; i++)
for (size_t j = 0; j < sizeof matrixA[0] / sizeof matrixA[0][0]; j++)
printf("%+f%+f*I\n", creal(matrixA[i][j]), cimag(matrixA[i][j]));
return EXIT_SUCCESS;
}
Here's a simple solution using scanf() and the format shown in the examples.
It writes the values in the same format that it reads them — the output can be scanned by the program as input.
/* SO 7438-4793 */
#include <stdio.h>
static int read_complex(FILE *fp, double *r, double *i)
{
int offset = 0;
char sign[2];
if (fscanf(fp, "%lg%[-+]%lg*%*[iI]%n", r, sign, i, &offset) != 3 || offset == 0)
return EOF;
if (sign[0] == '-')
*i = -*i;
return 0;
}
int main(void)
{
double r;
double i;
while (read_complex(stdin, &r, &i) == 0)
printf("%g%+g*I\n", r, i);
return 0;
}
Sample input:
0.2e-3+0.3*I 0.1+0.1*I
0.3+0.1*I 0.1+0.4*I
-1.2-3.6*I -6.02214076e23-6.62607015E-34*I
Output from sample input:
0.0002+0.3*I
0.1+0.1*I
0.3+0.1*I
0.1+0.4*I
-1.2-3.6*I
-6.02214e+23-6.62607e-34*I
The numbers at the end with large exponents are Avogadro's Number and the Planck Constant.
The format is about as stringent are you can make it with scanf(), but, although it requires a sign (+ or -) between the real and imaginary parts and requires the * and I to be immediately after the imaginary part (and the conversion will fail if the *I is missing), and accepts either i or I to indicate the imaginary value:
It doesn't stop the imaginary number having a second sign (so it will read a value such as "-6+-4*I").
It doesn't stop there being white space after the mandatory sign (so it will read a value such as "-6+ 24*I".
It doesn't stop the real part being on one line and the imaginary part on the next line.
It won't handle either a pure-real number or a pure-imaginary number properly.
The scanf() functions are very flexible about white space, and it is very hard to prevent them from accepting white space. It would require a custom parser to prevent unwanted spaces. You could do that by reading the numbers and the markers separately, as strings, and then verifying that there's no space and so on. That might be the best way to handle it. You'd use sscanf() to convert the string read after ensuring there's no embedded white space yet the format is correct.
I do not know which IDE you are using for C, so I do not understand this ./testprog <test.data.
I have yet to find an IDE that does not drive me bonkers. I use a Unix shell running in a terminal window. Assuming that your program name is testprog and the data file is test.data, typing ./testprog < test.data runs the program and feeds the contents of test.data as its standard input. On Windows, this would be a command window (and I think PowerShell would work much the same way).
I used fgets to read each line of the text file. Though I know the functionality of sscanf, I do not know how to parse an entire line, which has about 23 elements per line. If the number of elements in a line are few, I know how to parse it. Could you help me about it?
As I noted in a comment, the SO Q&A How to use sscanf() in loops? explains how to use sscanf() to read multiple entries from a line. In this case, you will need to read multiple complex numbers from a single line. Here is some code that shows it at work. It uses the POSIX getline() function to read arbitrarily long lines. If it isn't available to you, you can use fgets() instead, but you'll need to preallocate a big enough line buffer.
#include <stdio.h>
#include <stdlib.h>
#include <complex.h>
#ifndef CMPLX
#define CMPLX(r, i) ((double complex)((double)(r) + I * (double)(i)))
#endif
static size_t scan_multi_complex(const char *string, size_t nvalues,
complex double *v, const char **eoc)
{
size_t nread = 0;
const char *buffer = string;
while (nread < nvalues)
{
int offset = 0;
char sign[2];
double r, i;
if (sscanf(buffer, "%lg%[-+]%lg*%*[iI]%n", &r, sign, &i, &offset) != 3 || offset == 0)
break;
if (sign[0] == '-')
i = -i;
v[nread++] = CMPLX(r, i);
buffer += offset;
}
*eoc = buffer;
return nread;
}
static void dump_complex(size_t nvalues, complex double values[nvalues])
{
for (size_t i = 0; i < nvalues; i++)
printf("%g%+g*I\n", creal(values[i]), cimag(values[i]));
}
enum { NUM_VALUES = 128 };
int main(void)
{
double complex values[NUM_VALUES];
size_t nvalues = 0;
char *buffer = 0;
size_t buflen = 0;
int length;
size_t lineno = 0;
while ((length = getline(&buffer, &buflen, stdin)) > 0 && nvalues < NUM_VALUES)
{
const char *eoc;
printf("Line: %zu [[%.*s]]\n", ++lineno, length - 1, buffer);
size_t nread = scan_multi_complex(buffer, NUM_VALUES - nvalues, &values[nvalues], &eoc);
if (*eoc != '\0' && *eoc != '\n')
printf("EOC: [[%s]]\n", eoc);
if (nread == 0)
break;
dump_complex(nread, &values[nvalues]);
nvalues += nread;
}
free(buffer);
printf("All done:\n");
dump_complex(nvalues, values);
return 0;
}
Here is a data file with 8 lines with 10 complex numbers per line):
-1.95+11.00*I +21.72+64.12*I -95.16-1.81*I +64.23+64.55*I +28.42-29.29*I -49.25+7.87*I +44.98+79.62*I +69.80-1.24*I +61.99+37.01*I +72.43+56.88*I
-9.15+31.41*I +63.84-15.82*I -0.77-76.80*I -85.59+74.86*I +93.00-35.10*I -93.82+52.80*I +85.45+82.42*I +0.67-55.77*I -58.32+72.63*I -27.66-81.15*I
+87.97+9.03*I +7.05-74.91*I +27.60+65.89*I +49.81+25.08*I +44.33+77.00*I +93.27-7.74*I +61.62-5.01*I +99.33-82.80*I +8.83+62.96*I +7.45+73.70*I
+40.99-12.44*I +53.34+21.74*I +75.77-62.56*I +54.16-26.97*I -37.02-31.93*I +78.20-20.91*I +79.64+74.71*I +67.95-40.73*I +58.19+61.25*I +62.29-22.43*I
+47.36-16.19*I +68.48-15.00*I +6.85+61.50*I -6.62+55.18*I +34.95-69.81*I -88.62-81.15*I +75.92-74.65*I +85.17-3.84*I -37.20-96.98*I +74.97+78.88*I
+56.80+63.63*I +92.83-16.18*I -11.47+8.81*I +90.74+42.86*I +19.11-56.70*I -77.93-70.47*I +6.73+86.12*I +2.70-57.93*I +57.87+29.44*I +6.65-63.09*I
-35.35-70.67*I +8.08-21.82*I +86.72-93.82*I -28.96-24.69*I +68.73-15.36*I +52.85+94.65*I +85.07-84.04*I +9.98+29.56*I -78.01-81.23*I -10.67+13.68*I
+83.10-33.86*I +56.87+30.23*I -78.56+3.73*I +31.41+10.30*I +91.98+29.04*I -9.20+24.59*I +70.82-19.41*I +29.21+84.74*I +56.62+92.29*I +70.66-48.35*I
The output of the program is:
Line: 1 [[-1.95+11.00*I +21.72+64.12*I -95.16-1.81*I +64.23+64.55*I +28.42-29.29*I -49.25+7.87*I +44.98+79.62*I +69.80-1.24*I +61.99+37.01*I +72.43+56.88*I]]
-1.95+11*I
21.72+64.12*I
-95.16-1.81*I
64.23+64.55*I
28.42-29.29*I
-49.25+7.87*I
44.98+79.62*I
69.8-1.24*I
61.99+37.01*I
72.43+56.88*I
Line: 2 [[-9.15+31.41*I +63.84-15.82*I -0.77-76.80*I -85.59+74.86*I +93.00-35.10*I -93.82+52.80*I +85.45+82.42*I +0.67-55.77*I -58.32+72.63*I -27.66-81.15*I]]
-9.15+31.41*I
63.84-15.82*I
-0.77-76.8*I
-85.59+74.86*I
93-35.1*I
-93.82+52.8*I
85.45+82.42*I
0.67-55.77*I
-58.32+72.63*I
-27.66-81.15*I
Line: 3 [[+87.97+9.03*I +7.05-74.91*I +27.60+65.89*I +49.81+25.08*I +44.33+77.00*I +93.27-7.74*I +61.62-5.01*I +99.33-82.80*I +8.83+62.96*I +7.45+73.70*I]]
87.97+9.03*I
7.05-74.91*I
27.6+65.89*I
49.81+25.08*I
44.33+77*I
93.27-7.74*I
61.62-5.01*I
99.33-82.8*I
8.83+62.96*I
7.45+73.7*I
Line: 4 [[+40.99-12.44*I +53.34+21.74*I +75.77-62.56*I +54.16-26.97*I -37.02-31.93*I +78.20-20.91*I +79.64+74.71*I +67.95-40.73*I +58.19+61.25*I +62.29-22.43*I]]
40.99-12.44*I
53.34+21.74*I
75.77-62.56*I
54.16-26.97*I
-37.02-31.93*I
78.2-20.91*I
79.64+74.71*I
67.95-40.73*I
58.19+61.25*I
62.29-22.43*I
Line: 5 [[+47.36-16.19*I +68.48-15.00*I +6.85+61.50*I -6.62+55.18*I +34.95-69.81*I -88.62-81.15*I +75.92-74.65*I +85.17-3.84*I -37.20-96.98*I +74.97+78.88*I]]
47.36-16.19*I
68.48-15*I
6.85+61.5*I
-6.62+55.18*I
34.95-69.81*I
-88.62-81.15*I
75.92-74.65*I
85.17-3.84*I
-37.2-96.98*I
74.97+78.88*I
Line: 6 [[+56.80+63.63*I +92.83-16.18*I -11.47+8.81*I +90.74+42.86*I +19.11-56.70*I -77.93-70.47*I +6.73+86.12*I +2.70-57.93*I +57.87+29.44*I +6.65-63.09*I]]
56.8+63.63*I
92.83-16.18*I
-11.47+8.81*I
90.74+42.86*I
19.11-56.7*I
-77.93-70.47*I
6.73+86.12*I
2.7-57.93*I
57.87+29.44*I
6.65-63.09*I
Line: 7 [[-35.35-70.67*I +8.08-21.82*I +86.72-93.82*I -28.96-24.69*I +68.73-15.36*I +52.85+94.65*I +85.07-84.04*I +9.98+29.56*I -78.01-81.23*I -10.67+13.68*I]]
-35.35-70.67*I
8.08-21.82*I
86.72-93.82*I
-28.96-24.69*I
68.73-15.36*I
52.85+94.65*I
85.07-84.04*I
9.98+29.56*I
-78.01-81.23*I
-10.67+13.68*I
Line: 8 [[+83.10-33.86*I +56.87+30.23*I -78.56+3.73*I +31.41+10.30*I +91.98+29.04*I -9.20+24.59*I +70.82-19.41*I +29.21+84.74*I +56.62+92.29*I +70.66-48.35*I]]
83.1-33.86*I
56.87+30.23*I
-78.56+3.73*I
31.41+10.3*I
91.98+29.04*I
-9.2+24.59*I
70.82-19.41*I
29.21+84.74*I
56.62+92.29*I
70.66-48.35*I
All done:
-1.95+11*I
21.72+64.12*I
-95.16-1.81*I
64.23+64.55*I
28.42-29.29*I
-49.25+7.87*I
44.98+79.62*I
69.8-1.24*I
61.99+37.01*I
72.43+56.88*I
-9.15+31.41*I
63.84-15.82*I
-0.77-76.8*I
-85.59+74.86*I
93-35.1*I
-93.82+52.8*I
85.45+82.42*I
0.67-55.77*I
-58.32+72.63*I
-27.66-81.15*I
87.97+9.03*I
7.05-74.91*I
27.6+65.89*I
49.81+25.08*I
44.33+77*I
93.27-7.74*I
61.62-5.01*I
99.33-82.8*I
8.83+62.96*I
7.45+73.7*I
40.99-12.44*I
53.34+21.74*I
75.77-62.56*I
54.16-26.97*I
-37.02-31.93*I
78.2-20.91*I
79.64+74.71*I
67.95-40.73*I
58.19+61.25*I
62.29-22.43*I
47.36-16.19*I
68.48-15*I
6.85+61.5*I
-6.62+55.18*I
34.95-69.81*I
-88.62-81.15*I
75.92-74.65*I
85.17-3.84*I
-37.2-96.98*I
74.97+78.88*I
56.8+63.63*I
92.83-16.18*I
-11.47+8.81*I
90.74+42.86*I
19.11-56.7*I
-77.93-70.47*I
6.73+86.12*I
2.7-57.93*I
57.87+29.44*I
6.65-63.09*I
-35.35-70.67*I
8.08-21.82*I
86.72-93.82*I
-28.96-24.69*I
68.73-15.36*I
52.85+94.65*I
85.07-84.04*I
9.98+29.56*I
-78.01-81.23*I
-10.67+13.68*I
83.1-33.86*I
56.87+30.23*I
-78.56+3.73*I
31.41+10.3*I
91.98+29.04*I
-9.2+24.59*I
70.82-19.41*I
29.21+84.74*I
56.62+92.29*I
70.66-48.35*I
The code would handle lines with any number of entries on a line (up to 128 in total because of the limit on the size of the array of complex numbers — but that can be fixed too.

syscall read acting weird

c lang, ubuntu
so i have a task - write a menu with these 3 options:
1. close program
2. show user id
3. show current working directory
i can only use 3 libraries - unistd.h, sys/syscall.h, sys/sysinfo.h.
so no printf/scanf
i need to use an array of a struct im given, that has a function pointer,
to call the function the user wants to use.
problem is on options 2 & 3;
when i pick 2, on the first time it works fine (i think)
second time i pick 2, it works, but then when going to the third iteration,
it doesn't wait for an input, it takes '\n' as an input for some reason, then it says invalid input. (i checked what it takes as input with printf, i printed index after recalculating it and it because -39, so it means selection[0] = 10 = '\n')
that's the first problem, that i just cant find the solution for.
second problem is on the current working directory function;
the SYS_getcwd returns -1 for some reason, which means there's an error, but i cant figure it out.
any explanations for these things?
(also - slen and __itoa are functions i am given - slen returns the length of a string,
__itoa returns a char*, that was the string representation of an integer)
helper.h:
typedef struct func_desc {
char *name;
void (*func)(void);
} fun_desc;
main.c:
#include <unistd.h>
#include "helper.h"
#include <sys/syscall.h>
#include <sys/sysinfo.h>
void exitProgram();
void printID();
void currDir();
int main() {
fun_desc arrFuncs[3];
arrFuncs[0].name = "exitProgram";
arrFuncs[0].func = &exitProgram;
arrFuncs[1].name = "printID";
arrFuncs[1].func = &printID;
arrFuncs[2].name = "currDir";
arrFuncs[2].func = &currDir;
char selection[2];
int index;
const char* menu = "Welcome to the menu. Please pick one of the following actions:\n1.Close the program\n2.Print the current user's id\n3.Print the current directory's id\n";
while(1 == 1) {
syscall(SYS_write, 0, menu, slen(menu));
syscall(SYS_write, 0, "Your selection: ", slen("Your selection: "));
syscall(SYS_read, 1, selection, slen(selection)); //might be a problem
selection[1] = '\0';
index = selection[0] - '0' - 1;
if(index > 2)
syscall(SYS_write, 0, "Invalid input\n", slen("Invalid input\n"));
else
arrFuncs[index].func();
}
return(0);
}
void exitProgram() {
syscall(SYS_write, 0, "The program will close\n", slen("The program will close\n"));
syscall(SYS_exit);
}
void printID() { //problem
char* uid = __itoa(syscall(SYS_getuid));
syscall(SYS_write, 0, uid, slen(uid));
syscall(SYS_write, 0, "\n", slen("\n"));
}
void currDir() { //????
char* buf = __itoa(syscall(SYS_getcwd));
syscall(SYS_write, 0, buf, slen(buf));
syscall(SYS_write, 0, "\n", slen("\n"));
}
You're passing the wrong number of arguments to some of these system calls. In particular:
syscall(SYS_exit);
_exit() takes one argument: the exit code.
char* buf = __itoa(syscall(SYS_getcwd));
getcwd() takes two arguments: a pointer to a buffer to write the string to, and the length of that buffer. In practice, this probably looks something like:
char pathbuf[PATH_MAX];
syscall(SYS_getcwd, pathbuf, sizeof(pathbuf));
If you don't have the header which defines PATH_MAX, define it yourself. 4096 is an appropriate value.
Note that getcwd() writes a string into the buffer passed to it — it does not return a numeric identifier.
As an aside, you may want to save yourself some time by implementing a wrapper to write a string, e.g.
void putstring(const char *str) {
syscall(SYS_write, 0, str, slen(str));
}
since you seem to be doing that a lot.

fscanf not saving the data to struct?

I have an array of structs and they get saved into a file. Currently there are two lines in the file:
a a 1
b b 2
I am trying to read in the file and have the data saved to the struct:
typedef struct book{
char number[11];//10 numbers
char first[21]; //20 char first/last name
char last[21];
} info;
info info1[500]
into num = 0;
pRead = fopen("phone_book.dat", "r");
if ( pRead == NULL ){
printf("\nFile cannot be opened\n");
}
else{
while ( !feof(pRead) ) {
fscanf(pRead, "%s%s%s", info1[num].first, info1[num].last, info1[num].number);
printf{"%s%s%s",info1[num].first, info1[num].last, info1[num].number); //this prints statement works fine
num++;
}
}
//if I add a print statement after all that I get windows directory and junk code.
This makes me think that the items are not being saved into the struct. Any help would be great. Thanks!
EDIT: Okay so it does save it fine but when I pass it to my function it gives me garbage code.
When I call it:
sho(num, book);
My show function:
void sho (int nume, info* info2){
printf("\n\n\nfirst after passed= %s\n\n\n", info2[0].first); //i put 0 to see the first entry
}
I think you meant int num = 0;, instead of into.
printf{... is a syntax error, printf(... instead.
Check the result of fscanf, if it isn't 3 it hasn't read all 3 strings.
Don't use (f)scanf to read strings, at least not without specifying the maximum length:
fscanf(pRead, "%10s%20s%20s", ...);
But, better yet, use fgets instead:
fgets(info1[num].first, sizeof info1[num].first, pRead);
fgets(info1[num].last, sizeof info1[num].last, pRead);
fgets(info1[num].number, sizeof info1[num].number, pRead);
(and check the result of fgets, of course)
Make sure num doesn't go higher than 499, or you'll overflow info:
while(num < 500 && !feof(pRead)){.
1.-For better error handling, recommend using fgets(), using widths in your sscanf(), validating sscanf() results.
2.-OP usage of feof(pRead) is easy to misuse - suggest fgets().
char buffer[sizeof(info)*2];
while ((n < 500) && (fgets(buffer, sizeof buffer, pRead) != NULL)) {
char sentinel; // look for extra trailing non-whitespace.
if (sscanf(buffer, "%20s%20s%10s %c", info1[num].first,
info1[num].last, info1[num].number, &sentinel) != 3) {
// Handle_Error
printf("Error <%s>\n",buffer);
continue;
}
printf("%s %s %s\n", info1[num].first, info1[num].last, info1[num].number);
num++;
}
BTW: using %s does not work well should a space exists within a first name or within a last name.

Read lines from a file into character arrays

I'm completely new to C and I'm working on a program which has to read in 3 lines from a text file(two numbers and a mathematical symbol) and write out the result. So for example:
The text file looks like:
1
4
*
and my program should be able to read the 3 lines and write out something like "1*4 = 4" or something.
I managed to get to a point where i can read the 3 lines in and show them on screen, so I thought I should put the two numbers in one array and the symbol in another one. The problem is, that I tried to see if the arrays contain the numbers I put in them and my output has some huge numbers in it and I'm not sure why.
Here's the code i wrote:
#include <stdio.h>
#include <io.h>
#include <string.h>
int main(void)
{
int res = 1; /*Creates an integer to hold the result of the check for the file*/
const char *file = "input.txt"; /*String holding the name of the file with the input data*/
res = access(file,R_OK); /*Checks if the file "input.txt" exists*/
if(res == -1)
{ /*IF the file doesn't exist:*/
FILE *input = fopen("input.txt","w"); /*This creates a file called "input.txt" in the directory of the program*/
char write[] = "1\n1\n+"; /*This variable holds the string that's to be written to the file*/
fprintf(input,"%s",write); /*This writes the variable "write" to the file*/
printf("input.txt file created!"); /*Tells you the file is created*/
fclose(input); /*Closes the file after it's done*/
}
else
{ /*IF the file exists:*/
FILE *f = fopen("input.txt","r");
//char line[ 5000 ];
//while ( fgets ( line, sizeof line, f ) != NULL )
//{
// fputs ( line, stdout );
//}
char line[5000];
char nums[2];
char symbol[1];
int i = 0;
while(fgets(line,sizeof line,f)!=NULL)
{
i++;
if(i < 3)
{
fputs(nums,f);
}
else
{
fputs(symbol,f);
}
printf("%d,%d",nums,symbol);
}
printf("\n\n\n");
scanf("\n");
}
return 0;
}
Any help would be greatly appreciated!
Thank you in advance
If you require any more information i will provide it.
This is a self-explanatory algorithm. Also, here is the code that does the operation you are looking for. Generally, the complex operations are accomplished using stack, push and pop method. Once the operators are pushed. One need to apply the BODMAS rule,to evaluate the expression. Since the problem given to you is simple, a simple expression evaluation. This can be simply achieved by FIFO. Here is the algorithm, general explanation. Afterwards, the code is present. This code is well tested.You can extend it to do operations like +,-,division /, %, etc. If you like my answer please appreciate.
#include "stdio.h"
int main(int argc, char *argv[])
{
FILE *fp_op;
int buff[2]; /** assuming a simple operation, thus the buffer size is 3 only, the last one is to store the NULL **/
char operat_buff[2]; /** assuming this operation we can extend it to evaluate an expression **/
fp_op = fopen("calc.txt","rb");
if ( fp_op == 0 )
{
perror("The file doesn't exist to calculate\r\n");
goto error;
}
/** Read the two numbers here **/
fscanf(fp_op,"%d",&(buff[0]));
printf("The buff[1] = %d\r\n",buff[0]);
fscanf(fp_op,"%d",&(buff[1]));
printf("The buff[1] = %d\r\n",buff[1]);
/** read the next line now \n **/
operat_buff[0] = fgetc(fp_op);
/** read the actual character now **/
operat_buff[0] = fgetc(fp_op);
printf("The operat_buff[0] = %d\r\n",operat_buff[0]);
/** Read operation completed **/
/** use switch here **/
switch(operat_buff[0])
{
case '*':
printf("The multiplication result=%d\r\n",buff[0]*buff[1]);
break;
case '+':
printf("The Addition result=%d\r\n",buff[0]+buff[1]);
break;
default:
printf("Add more operations\r\n");
}
return 0;
error:
return -1;
}
I assume that the calc.txt was something like this.
calc.txt
3
5
*
Note: This code is compiled and verified.It compiles with zero warnings. It does the error checking too. You can directly copy and paste it.
What are you reading from the files are simply characters codes: the program has no way of figuring by itself that the character "4" corresponds to the integer number 4. The %d placeholder of printf expects int variables, or it won't work.
If you want just to print the characters you have to save them in char variables (or a char array) and use the placeholder %c in printf. If you want to actually use the numbers and symbols in your program you have more work to do.
Not only in C, but I think in most languages you have to "parse" the characters to numbers.
In C you can use the functions atoi or atol (you have to #include <stdlib.h>) in order to do this conversion.
In order to parse the symbol I'm afraid you will have to use an if or a switch to read the character and perform the operation accordingly.
For example your loop could look like:
while(fgets(line,sizeof line,f)!=NULL)
{
int op1;
int op2;
int res;
char symbol;
i++;
switch (i) {
case 1:
//First line is first operand
op1 = atoi(line);
printf("op1 %d\n",op1);
break;
case 3:
//Second line is second operand
op2 = atoi(line);
printf("op2 %d\n",op2);
break;
//Fifth line is the operator, could be +,-,%./ or anything
case 5:
symbol = line[0];
printf("operand %c\n",symbol);
switch(symbol) {
case '+':
res = op1+op2;
break;
case '-':
res = op1-op2;
break;
default:
//operation not defined, return
return;
}
printf("%d%c%d = %d",op1,symbol,op2,res);
}
}
printf("%d,%d",nums,symbol);
In your code nums and symbol are strings, you can't print them with %d. What you are getting are the addresses of the nums and symbol arrays, respectively - even if that's not the right way of printing an address.
You'll likely want to convert them to integers, using strtol or sscanf and then use those to perform the computation.

PCRE is not matching utf8 characters

I'm compiling a PCRE pattern with utf8 flag enabled and am trying to match a utf8 char* string against it, but it is not matching and pcre_exec returns negative. I'm passing the subject length as 65 to pcre_exec which is the number of characters in the string. I believe it expects the number of bytes so I have tried with increasing the argument till 70 but still get the same result. I don't know what else is making the match fail. Please help before I shoot myself.
(If I try without the flag PCRE_UTF8 however, it matches but the offset vector[1] is 30 which is index of the character just before a unicode character in my input string)
#include "stdafx.h"
#include "pcre.h"
#include <pcre.h> /* PCRE lib NONE */
#include <stdio.h> /* I/O lib C89 */
#include <stdlib.h> /* Standard Lib C89 */
#include <string.h> /* Strings C89 */
#include <iostream>
int main(int argc, char *argv[])
{
pcre *reCompiled;
int pcreExecRet;
int subStrVec[30];
const char *pcreErrorStr;
int pcreErrorOffset;
char* aStrRegex = "(\\?\\w+\\?\\s*=)?\\s*(call|exec|execute)\\s+(?<spName>\\w+)("
// params can be an empty pair of parenthesis or have parameters inside them as well.
"\\(\\s*(?<params>[?\\w,]+)\\s*\\)"
// paramList along with its parenthesis is optional below so a SP call can be just "exec sp_name" for a stored proc call without any parameters.
")?";
reCompiled = pcre_compile(aStrRegex, 0, &pcreErrorStr, &pcreErrorOffset, NULL);
if(reCompiled == NULL) {
printf("ERROR: Could not compile '%s': %s\n", aStrRegex, pcreErrorStr);
exit(1);
}
char* line = "?rt?=call SqlTxFunctionTesting(?înFîéld?,?outField?,?inOutField?)";
pcreExecRet = pcre_exec(reCompiled,
NULL,
line,
65, // length of string
0, // Start looking at this point
0, // OPTIONS
subStrVec,
30); // Length of subStrVec
printf("\nret=%d",pcreExecRet);
//int substrLen = pcre_get_substring(line, subStrVec, pcreExecRet, 1, &mantissa);
}
1)
char * q= "î";
printf("%d, %s", q[0], q);
Output:
63, ?
2) You must rebuild PCRE with PCRE_BUILD_PCRE16 (or 32) and PCRE_SUPPORT_UTF. And use pcre16.lib and/or pcre16.dll. Then you can try this code:
pcre16 *reCompiled;
int pcreExecRet;
int subStrVec[30];
const char *pcreErrorStr;
int pcreErrorOffset;
wchar_t* aStrRegex = L"(\\?\\w+\\?\\s*=)?\\s*(call|exec|execute)\\s+(?<spName>\\w+)("
// params can be an empty pair of paranthesis or have parameters inside them as well.
L"\\(\\s*(?<params>[?,\\w\\p{L}]+)\\s*\\)"
// paramList along with its paranthesis is optional below so a SP call can be just "exec sp_name" for a stored proc call without any parameters.
L")?";
reCompiled = pcre16_compile((PCRE_SPTR16)aStrRegex, PCRE_UTF8, &pcreErrorStr, &pcreErrorOffset, NULL);
if(reCompiled == NULL) {
printf("ERROR: Could not compile '%s': %s\n", aStrRegex, pcreErrorStr);
exit(1);
}
const wchar_t* line = L"?rt?=call SqlTxFunctionTesting( ?inField?,?outField?,?inOutField?,?fd? )";
const wchar_t* mantissa=new wchar_t[wcslen(line)];
pcreExecRet = pcre16_exec(reCompiled,
NULL,
(PCRE_SPTR16)line,
wcslen(line), // length of string
0, // Start looking at this point
0, // OPTIONS
subStrVec,
30); // Length of subStrVec
printf("\nret=%d",pcreExecRet);
for (int i=0;i<pcreExecRet;i++){
int substrLen = pcre16_get_substring((PCRE_SPTR16)line, subStrVec, pcreExecRet, i, (PCRE_SPTR16 *)&mantissa);
wprintf(L"\nret string=%s, length=%i\n",mantissa,substrLen);
}
3) \w = [0-9A-Z_a-z]. It doesn't contains unicode symbols.
4) This can really help: http://answers.oreilly.com/topic/215-how-to-use-unicode-code-points-properties-blocks-and-scripts-in-regular-expressions/
5) from PCRE 8.33 source (pcre_exec.c:2251)
/* Find out if the previous and current characters are "word" characters.
It takes a bit more work in UTF-8 mode. Characters > 255 are assumed to
be "non-word" characters. Remember the earliest consulted character for
partial matching. */

Resources