I have a very simple problem in C. I am reading a file linewise, and store it in
a buffer
char line[80];
Each line has the following structure:
Timings results : 2215543
Timings results : 22155431
Timings results : 221554332
Timings results : 2215543
What I am trying to do, is to extract the integer value from this line. Does C here provide any simple function that allows me to do that?
Thanks
Can use sscanf per line, like:
#include <stdio.h>
int time = -1;
char* str = "Timings results : 120012";
int n = sscanf(str, "Timings results : %d", &time);
in this case n == 1 means success
Yes - try atoi
int n=atoi(str);
In your example, you have a fixed prefix before the integer, so you could simply add an offset to szLine before passing it to atoi, e.g.
int offset=strlen("Timings results : ");
int timing=atoi(szLine + offset);
Pretty efficient, but doesn't cope well with lines which aren't as expected. You could check each line first though:
const char * prefix="Timings results : ";
int offset=strlen(prefix);
char * start=strstr(szLine, prefix);
if (start)
{
int timing=atoi(start+offset);
//do whatever you need to do
}
else
{
//line didn't match
}
You can also use sscanf for parsing lines like this, which makes for more concise code:
int timing;
sscanf(szLine, "Timings results : %d", &timing);
Finally, see also Parsing Integer to String C for further ideas.
Related
What I have till now is this. I am not able to figure out how to take the input as mentioned and solve this problem?
#include<stdio.h>
#include <stdlib.h>
#include<float.h>
int main()
{
char s[50];
float mil,min=FLT_MAX;
while(scanf("%s#%f",s,&mil)!=-1)
{
printf("%s\n",s);
if(mil<min)
min=mil;
}
}
EDIT: My problem is that when I print the string s inside the loop, "Zantro#16.15" is printed whereas I want only "Zantro" to be stored in s and 16.15 to be stored in mil
%s scans up until a whitespace. Scan up until a # instead.
while (scanf("%[^#]#%f", s, &mil) == 2)
Remember to specify the maximum buffer size in the scanning format to protect against overflows:
while (scanf("%49[^#]#%f", s, &mil) == 2)
Well the scanf function can not easily determine, that you want the # sign to be a delimiter. Therefore you need to add an extra step to split up the strings into proper parts and store them for later comparison.
Have a look at strtok function in c.
http://www.c-howto.de/tutorial/strings-zeichenketten/string-funktionen/string-zerteilen/
Here is a solution that prints the requested string:
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include <string.h>
int main()
{
char s[50];
char mins[50];
float mil,min=FLT_MAX;
int rc;
int done=0;
while (done == 0)
{
rc = scanf("%49[^#]#%f", s, &mil);
if (rc != 2)
{
done = 1;
continue;
}
if (mil < min)
{
min = mil;
strcpy(mins, s);
}
}
printf("%s\n", mins);
return 0;
}
Execution:
./sc
Zantro#16.15
Zirty#12.5
Gamry#9.8
Gamry
#include<stdio.h>
#include <stdlib.h>
#include<float.h>
int main()
{
char s[50];
float mil, min = FLT_MAX;
while (scanf("%[^#]#%f", s, &mil) == 2)
{
printf("%s\n", s);
if (mil < min)
min = mil;
}
}
Input:Zantro#16.15Zity#12.5Gamry#9.8
OutPut:
Zantro
Zity
Gamry
If you want to split your input in the scanf to string and float, you have to write those two types separately. For example, ("%s %f"). This string tells the function, what will be the arguments types. Therefore, if you write it like this ("%s#%f") the scanf function has a problem to understand, what will be the inputs types. In addition, if you write ("%s #%f") it will get two inputs like this " #". Your problem here is the space between the two arguments. Because, I didnt find how to get the input without this space. I'm recommending you to try splitting the input in another way.
For example, take one string that holds the intaier input to string buffer-> scanf("%s",sBuffer).
and split that to different variables after that.
I'm using the paillier library for cryptography.
There is a function namely paillier_ciphertext_to_bytes which converts to bytes. Upon checking the paillier.h, it has the return type void*.
I would like to take the string this generates which I believe is hex, and convert it to a decimal number using strtol.
However, when I cast the output of paillier_ciphertext_to_bytes to a char*, it doesn't work as expected.
This is my code
#include<stdio.h>
#include<stdlib.h>
#include<gmp.h>
//#include<paillier.h>
#include"paillier.h"
#include <string.h>
#include<malloc.h>
int main()
{
int n=4; //degree of polynomial
int i=0;
char* str;
paillier_pubkey_t *pub_key=(paillier_pubkey_t *)malloc(sizeof(paillier_pubkey_t));
paillier_prvkey_t *prv_key=(paillier_prvkey_t *)malloc(sizeof(paillier_prvkey_t));
paillier_keygen(4,&pub_key,&prv_key,paillier_get_rand_devrandom);
for(i=0;i<n;i++)
{
unsigned int p=rand()%20;
paillier_plaintext_t *ptext = paillier_plaintext_from_ui(p);
paillier_ciphertext_t *ctext;
ctext = paillier_enc(0, pub_key, ptext, paillier_get_rand_devrandom);
str = (char*)paillier_ciphertext_to_bytes(n,ctext);
printf("str==[%s]\n",str);
printf("number_str==[%d]\n",(int)strtol(str,NULL,16));
}
return 0;
}
This is the output I get
str==[]
number_str==[0]
str==[]
number_str==[0]
str==[]
number_str==[0]
str==[]
number_str==[0]
This is the paillier.h library code, where I looked up the signature of paillier_ciphertext_to_bytes
Side note,
I only want to convert the encryption to a number. Actually there is no reason for me to believe that paillier_ciphertext_to_bytes can be cast to a char*. So, I've also tried converting it to an int* and then print out it's value as follows
int* myintp;
myintp = (int*)paillier_ciphertext_to_bytes(n,ctext);
printf("number==[%d]\n",*myintp);
This always give me an integer number, but I'm not sure if this is correct(the decimal representation of the encrypted string)
EDIT :
As per Felix's comment, I've tried this
#include<stdio.h>
#include<stdlib.h>
#include<gmp.h>
//#include<paillier.h>
#include"paillier.h"
#include <string.h>
#include<malloc.h>
int main()
{
int n=4; //degree of polynomial
int i=0;
void* myvoid;
FILE* fp;
fp = fopen("file.txt","a");
paillier_pubkey_t *pub_key=(paillier_pubkey_t *)malloc(sizeof(paillier_pubkey_t));
paillier_prvkey_t *prv_key=(paillier_prvkey_t *)malloc(sizeof(paillier_prvkey_t));
paillier_keygen(4,&pub_key,&prv_key,paillier_get_rand_devrandom);
for(i=0;i<n;i++)
{
unsigned int p=rand()%20;
paillier_plaintext_t *ptext = paillier_plaintext_from_ui(p);
paillier_ciphertext_t *ctext;
ctext = paillier_enc(0, pub_key, ptext, paillier_get_rand_devrandom);
myvoid=paillier_ciphertext_to_bytes(PAILLIER_BITS_TO_BYTES(pub_key->bits)*2, ctext);
fwrite(myvoid, 1, PAILLIER_BITS_TO_BYTES(pub_key->bits)*2, fp);
printf("as int : %d\n",*(int*)myvoid);
printf("as str : %d\n",(int)strtol((char*)myvoid,NULL,16));
}
fclose(fp);
return 0;
}
But I get unprintable characters in my output file when I try to print myvoid, and when I cast to integer and string, I get this output
as int : 31136768
as str : 0
as int : 493106432
as str : 0
as int : 493111552
as str : 0
as int : 493092864
as str : 0
Without knowing the library in question, it's pretty clear from the name of the function what it does: It gives you the actual encrypted bytes contained in some library-specific container type. Of course you can just take it as char * (there's no need to cast and you shouldn't, but that's another question).
Typically encrypted data contains any possible byte value, which includes 0 as well as non-printable characters and so on. So, having a char * pointer to it doesn't make it a C string. What you would do now is encode it in some ascii encoding, often base64 is used. This would give you a string representation suitable for writing to a file or sending in an email.
About the part of interpreting it as an int: This is a very bad idea. As encrypted data can contain any possible byte values, it really should only be treated as this: bytes. With int you could have for example two different representations of 0, so you'd lose information. And that's just one example of what could go wrong.
char * or void * is the correct type for a sequence of arbitrary bytes. Of course, to do anything useful with it, you need to know how many bytes there are in the encrypted form. Look in your library's documentation for how to know.
I'm making a calc function which is meant to check if the input is valid. So, I'll have 2 strings, one with what the user inputs (eg, 3+2-1 or maybe dog - which will be invalid), and one with the ALLOWED characters stored in a string, eg '123456789/*-+.^' .
I'm not sure how can I do this and have trouble getting it started. I know a few functions such as STRMCP, and the popular ones from the string.h file, but I have no idea how to use them to check every input.
What is the most simplest way to do this?
One way of proceeding is the following.
A string is an array of ascii codes. So if your string is
char formula[50];
then you have a loop
int n =0;
while (formula[n]!=0)
{
if ( (formula[n]<........<<your code here>> ))
{printf("invalid entry\n\n"); return -1; //-1 = error code
n++;
}
you need to put the logic into the loop, but you can test the ascii codes of each character with this loop.
There may be a more elegant way of solving this, but this will work if you put the correct conditional statement here to check the ascii code of each character.
The while statement checks to see ifyou got to the end of the string.
Here's a demonstration of how use strpbrk() to check all characters in a string are in your chosen set:
#include <string.h>
#include <stdio.h>
const char alphabet[] = "123456789/*+-=.^";
int main(void) {
const char a[] = "3+2-1";
const char b[] = "dog";
char *res = strpbrk(a, alphabet);
printf("%s %s\n", a, (res) ? "true" : "false");
res = strpbrk(b, alphabet);
printf("%s %s\n", b, (res) ? "true" : "false");
return 0;
}
That's not the fastest way to do this, but it's very easy to use.
However, if you are writing a calculator function, you really want to parse the string at the same time. A typical strategy would be to have two types of entity - operators (+-/*^) and operands (numbers, so -0.1, .0002, 42, etc). You would extract these from the string as you parse it, and just fail if you hit an invalid character. (If you need to handle parentheses, you'll need a stack for the parsing.... and you'll likely need to work with a stack anyway to process and evaluate the expression overall.)
I am trying to write a function (and failing badly!!) that passes an int as a parameter and returns a string which is generated from a mysql query - see below code:
I would like after I have have that working like to be able to pass a number of parameters (1 int and 2 chars) and have returned 3 strings, I guess those will require a struct and pointers but i'll start with the simple stuff.. crawl first..run later :)
Here is the code I have written I have removed the function but it's failing on compile at the line
retString = strFunction(Value);
with the error:
warning: assignment makes pointer from integer without a cast [enabled by default]
I can post the full code if required..
Many Thanks in advance.
int main(int argc, char *argv[])
{
char *retString;
retString = strFunction(Value);
printf("The Return string is: %s", retString);
Exit (0);
}
char *strFunction(int Value)
{
perform code here using value;
Return retString;
}
Okay here's the full code.. messy I know... embarrassment got the better of me posting originally..
int main(int argc, char *argv[])
{
int Exhibit = 1;
char *rtn_Exhibition;
rtn_Exhibition = rtn_ex(Exhibit);
printf("The Exhibition is set to: %s", rtn_Exhibition);
}
char *rtn_ex(int Exhibit)
{
static char selectEx[2];
unsigned int i;
char selectEx_rtn[20];
memset(selectEx, 0, sizeof(selectEx));
sprintf(selectEx, "SELECT exhibition_description FROM exhibitions WHERE exhibition_id='%d'",Exhibit);
printf("\nThe SELECT statement you have built is: %s\n", selectEx );
connectDB();
if (mysql_query (conn, selectEx) != 0)
{
print_error (conn, "mysql_query() failed");
}
else
{
res_set = mysql_store_result (conn); /* generate result set */
// printf("The value of the result set is: %d\n", res_set);
if (res_set == NULL)
{
print_error(conn, "mysql_store_result() failed");
}
else
{
//process_result_set(conn, res_set);
MYSQL_ROW row;
while ((row = mysql_fetch_row (res_set)) != NULL)
{
for (i = 0; i < mysql_num_fields (res_set); i++)
{
sprintf(selectEx_rtn, "The exhibition name is: %s", (row[i]));
}
}
}
mysql_free_result(res_set);
}
disconnectDB();
return selectEx_rtn;
}
Hi T Thanks for your response, in answer to your comments:
1) That's correct, I didn't spot that. Yes there are 70 characters for the SELECT statement + the int that goes in the single quotes which will be a 1-9 number. I have adjusted the array as now 80 characters
2) The MYSQL_RES pointer is set earlier in the program:
MYSQL_RES *res_set;
3) I adjusted this to 30 characters but I get an error stating that selectEX_rtn warning: function returns address of local variable. I changed selectEx_rtn to a pointer and the function works but dies straight afterwards with a segmentation fault
You have lots of errors here.
you declare static char selectEx[2]; as a character array that has a width of two characters, yet later on you attempt to do: sprintf(selectEx, "SELECT exhibition_description FROM exhibitions WHERE exhibition_id='%d'",Exhibit);. This will result in a buffer overflow. For the static part of the query you need 70 characters. Assuming that you are using 32-bit integers, you will need another 10 characters to insure that you can hold the longest it. From this you should declare selectEX to be at least 80 characters wide. Suggestion: Set the size of selectEX to at least 80 characters wide (and double check my counting of the number of characters needed).
In this line of code res_set = mysql_store_result (conn); you are using res_set without declaring it. It is possible that the compiler is assuming that res_set is an int and it appears that mysql_store_result is returning a pointer. This might be the source of your error. Suggestion: declare res_set correctly.
In this line of code sprintf(selectEx_rtn, "The exhibition name is: %s", (row[i])); you have declared selectEX to be a twenty character wide array (char selectEx_rtn[20];). Yet the static part, i.e. "The exhibition name is: " requires 24 characters. Another buffer-overflow here, and that is not counting the number of characters in row[i]. Suggestion: Change the declaration of selectEx to be wide enough to hold the data. Additionally, using a width specifier with the %s, i.e. %15s, may help.
Hope this helps,
T
I'm new to C
i'm asked to check if the format of the text file input is right or not!
the file should have lines like this :
1-float
2-('+'/'*'/'-')
3-flaot
4-'='
5-the result of the above operation
6-';'
I read the file and place each char in an array but have no idea what to do next
here is my code
#include <stdio.h>
#include <conio.h>
/*Max number of characters to be read/write from file*/
#define MAX_CHAR_FOR_FILE_OPERATION 1000000
int main()
{
char *filename = "D:\input.txt";
FILE *fp;
char text[MAX_CHAR_FOR_FILE_OPERATION];
int i;
fp = fopen(filename, "r");
if(fp == NULL)
{
printf("File Pointer is invalid\n");
return -1;
}
//Ensure array write starts from beginning
i = 0;
//Read over file contents until either EOF is reached or maximum characters is read and store in character array
while( (fgets(&text[i++],sizeof(char)+1,fp) != NULL) && (i<MAX_CHAR_FOR_FILE_OPERATION) ) ;
//Ensure array read starts from beginning
fclose(fp);
getche();
return 0;
}
The easiest solution I can think of is to create an automata. That could be an enum with steps, for exemple:
enum AUTOMATE
{
FirstFloat = 0,
FirstSign,
SecondFloat,
EqualSign,
Answer
};
More info on how to use enum here : http://msdn.microsoft.com/en-us/library/whbyts4t.aspx
If you already have all each char in an array, iterate over the entire array using whichever loop you want, and check the integer value of each char. Use this table http://www.asciitable.com/ to check weather the integer value represents a number or a sign (-, +, =, etc). When each step is passed, tell your automate to go further (+=1). If you reach the end, you verified it. If not, then format is wrong.
It is not 100% clear what you want to do here.
If all you want to do is check that the expression is syntactically correct, that's one thing. If you want to check that it is also arithmetically correct (i.e. that the result on the RHS of the = is actually the result of the arithmetic expression on the LHS), that's another.
In either case, you must parse the input lines. There are several ways of doing this. The canonical, general, and robust way is to tokenize the lines with a lexer and pass the tokens from the lexer to a parser, which is a kind of finite state machine that “knows” the grammar of the language you are trying to parse (in this case infix arithmetic expressions). Given that you asked this question, it's reasonable to assume that you haven't got to this kind of material yet.
In your case, you are only dealing with simple infix arithmetic expressions of the form:
NUMBER OPERATOR NUMBER = NUMBER ;
You can get away with checking for lines that “look” exactly like this with one of the scanf() family of functions, but this is a fragile solution: if you add another term to the expression on the left, it will break; it takes considerable care to craft the correct format string; and it does not check for arithmetic correctness.
If all you need is something this simple, you can do it like this (I have omitted the file I/O):
#include <stdio.h>
#include <stdbool.h>
#define OPERATOR_CLASS "[-+/*]"
bool is_a_binary_infix_expression(const char *expr)
{
int count; // Count returned by sscanf()
float left_opd; // Left operand
char operator[2] = {'\0'}; // Operator
float right_opd; // Right operand
float result; // Result
char junk; // Trailing junk
// Format specifier for sscanf():
const char *format = "%f %1" OPERATOR_CLASS "%f =%f ; %c";
// Attempt conversion:
count = sscanf(expr, format, &left_opd, operator, &right_opd, &result, &junk);
// If exactly 4 conversions succeeded, the expression was good. If fewer,
// the conversion failed prematurely. If 5, there was trailing junk:
return count==4;
}
int main(void) {
int i;
int n_lines;
char *lines[]={
"1.5+2.2=3.7;",
"1.5 + 2.2 = 3.7 ; ",
"a+2.2=3.7;",
"1.5+2.2=3.7;x",
};
n_lines = (int)sizeof(lines)/sizeof(char *);
for(i=0; i<n_lines; i++) {
printf("'%s' is %s\n", lines[i], is_a_binary_infix_expression(lines[i]) ? "OK" : "NOT OK");
}
return 0;
}
This only checks for syntactic correctness. If you want to check for arithmetic correctness, you can switch on the operand to compute the correct result and compare that with the result extracted from the input line, but be careful not to fall into the trap of doing a direct comparison with ==.