C, how to get undefined part of string - c

I started learning C language about 1 week, and I'm trying to build my first programs. I'm coming from Python, so the C syntax isn't very clear for me, and I haven't understand the solutions that I found online.
So, if I have this string:
char str[50] = "dimension[1080,720];"
and i want to create two integer variables that containes 1080 and 720 and string var that contains the first string. But these two numbers can change, and they can have random cifras. So, i wanted my output is
int x = 1080
int y = 720
*the values are always two, but the lenght can change.
How can i do that?
Second version:
So, if I have this string:
char str[50] = "dimension["string",1080,720];"
and i want to create two integer variables that containes 1080 and 720 and string var that contains the first string. But these two numbers can change, and they can have random cifras. So, i wanted my output is
char str[1000] = "string";
int x = 1080
int y = 720
the values are always three, but the lenght can change.
How can i do that?

use sscanf function
int main(void)
{
char str[] = "dimension[1080,720];";
int x,y;
if(sscanf(str, "dimension[%d,%d", &x, &y) != 2) {printf("Error\n");}
else printf("X=%d Y=%d", x, y);
}
Question two:
int main(void)
{
char str[] = "dimension[\"string\",1080,720];";
char str1[20];
int x,y;
char *ptr = strstr(str, "[");
char *ptr1;
size_t len;
memcpy(str1, ptr + 2, len = (ptr1 = strchr(ptr + 2, '"')) - (ptr + 2));
str[len] = 0;
if(sscanf(ptr1 + 2, "%d,%d", &x, &y) != 2) {printf("Error\n");}
else printf("Str = %s X=%d Y=%d", str1, x, y);
}

The sscanf answer is perfect, but not very flexible. I add this in case you want more flexibility to parse strings. You can do it with regular expressions and in your case would be something like:
Piece of code taken from https://gist.github.com/ianmackinnon/3294587
I have added some modification to extract the numbers to the variables
#include <stdio.h>
#include <string.h>
#include <regex.h>
#include <stdlib.h>
int main ()
{
// Define regexp and input
char * source = "dimension[\"string\",1080,720];";
char * regexString = "[a-z]+\\[\"([a-z]+)\",([0-9]+),([0-9]+)\\]";
size_t maxMatches = 3;
size_t maxGroups = 4;
// Variables we want to extract from the input
char* str;
int n1;
int n2;
regex_t regexCompiled;
regmatch_t groupArray[maxGroups];
unsigned int m;
char * cursor;
if (regcomp(&regexCompiled, regexString, REG_EXTENDED))
{
printf("Could not compile regular expression.\n");
return 1;
};
m = 0;
cursor = source;
for (m = 0; m < maxMatches; m ++)
{
if (regexec(&regexCompiled, cursor, maxGroups, groupArray, 0))
break; // No more matches
unsigned int g = 0;
unsigned int offset = 0;
for (g = 0; g < maxGroups; g++)
{
if (groupArray[g].rm_so == (size_t)-1)
break; // No more groups
if (g == 0)
offset = groupArray[g].rm_eo;
char cursorCopy[strlen(cursor) + 1];
strcpy(cursorCopy, cursor);
cursorCopy[groupArray[g].rm_eo] = 0;
printf("Match %u, Group %u: [%2u-%2u]: %s\n",
m, g, groupArray[g].rm_so, groupArray[g].rm_eo,
cursorCopy + groupArray[g].rm_so);
switch (g)
{
case 1:
// Copy to the string now that we know the length
str = malloc(strlen(cursor)+1);
strcpy(str,cursorCopy + groupArray[g].rm_so);
break;
case 2:
n1 = (int) strtol(cursorCopy + groupArray[g].rm_so, (char **)NULL, 10); //(cursorCopy + groupArray[g].rm_so,10);
break;
case 3:
n2 = (int) strtol(cursorCopy + groupArray[g].rm_so, (char **)NULL, 10); //(cursorCopy + groupArray[g].rm_so,10);
break;
}
}
cursor += offset;
}
regfree(&regexCompiled);
printf("Matches in variables: %s - %d - %d \n",str,n1,n2);
return 0;
}
This for me prints
Match 0, Group 0: [ 0-28]: dimension["string",1080,720]
Match 0, Group 1: [11-17]: string
Match 0, Group 2: [19-23]: 1080
Match 0, Group 3: [24-27]: 720
Matches in variables: string - 1080 - 720

Related

Splitting a char based on delimiters and covert them to integers

I'm trying to split a given char into number of neopixels and colours which the neopixel in the strip should have. The format is: first the neopixel number, then the given color; next neopixel number, next given colour for that neopixel. I managed to split the given char into these and print them out. This is the first piece of the code and is testable and working.
Next I want to evaluate the given data and based on the colour and number of neopixel send them to my setPixel function. The important arguments are the pixelNumber (1st element of the given data) and r,g,b (2d element of the given data). r, g, b values are determind by a switch case, for example 1 needs to be r:255, G:230, C:560 and so on. This piece of code is "pseudocode" and can not be tested yet, it gives an indication of what needs to happen next.
The problem:
I don't know how to convert the split data into variables which I can use in my case() and how to convert the neopixelNumber to an int. Any help appreciated!
Code:
#include <stdio.h>
#include "string.h"
#include <stdlib.h>
int split (const char *txt, char delim, char ***tokens)
{
int *tklen, *t, count = 1;
char **arr, *p = (char *) txt;
while (*p != '\0') if (*p++ == delim) count += 1;
t = tklen = calloc (count, sizeof (int));
for (p = (char *) txt; *p != '\0'; p++) *p == delim ? *t++ : (*t)++;
*tokens = arr = malloc (count * sizeof (char *));
t = tklen;
p = *arr++ = calloc (*(t++) + 1, sizeof (char *));
while (*txt != '\0')
{
if (*txt == delim)
{
p = *arr++ = calloc (*(t++) + 1, sizeof (char *));
txt++;
}
else *p++ = *txt++;
}
free (tklen);
return count;
}
int main()
{
/* will split a given char into a neopixel number and a color (example: 1 : red, 2, blue) */
/* this part is working and testable */
char **singleNeopixelData;
char **splittedIntoPixelNumberAndColour;
const char *fullNeopixelData = "51,0;52,1;60,0;61,1"; // neopixel number , colour ;
int totalAmountNeopixels, counterNeopixelsAmount, totalAmountNeopixelsData, counterNeopixelsData;
totalAmountNeopixels = split (fullNeopixelData, ',', &singleNeopixelData);
for (counterNeopixelsAmount = 0; counterNeopixelsAmount < totalAmountNeopixels; counterNeopixelsAmount++) {
totalAmountNeopixelsData = split (singleNeopixelData[counterNeopixelsAmount], ';', &splittedIntoPixelNumberAndColour);
int pixel = 0;
for (counterNeopixelsData = 0; counterNeopixelsData < totalAmountNeopixelsData; counterNeopixelsData++) {
printf ("%s\n", splittedIntoPixelNumberAndColour[counterNeopixelsData]);
}
}
// bridge between those two pieces of code is what i'm looking for :)
/* pseudo code for what needs to happen
for() { // loop through created array
int r, g, b;
switch (neopixelColour) { // check give number and decide which color the pixel is going to be
case 0:
r = 0;
g = 0;
b = 0;
break;
case 1:
r = 255;
g = 0;
b = 0;
break;
}
setPixel(pPixelArray, pixelNumber, r, g, b); // assign pixelnumer and colour
}
showPixels(); // show output to neopixel strip
*/
}
I tried to convert them using typecasting but unfortunately that doesn't work.

Adding large integer values in C [duplicate]

This question already has answers here:
How do you store an arbitrarily large integer value in memory?
(8 answers)
Closed 2 years ago.
This is a fairly simple question:
How to get 2 unsigned integer values and add them in C for the following input constraint.
0 <= A, B <= 10^98
I know I can take the input as maybe a string but still I had this question in mind.
I have written the below code but it will not be able to take such a big value of 10^98
#include <stdio.h>
int main() {
unsigned long long int a, b;
int x = scanf("%llu%llu", &a, &b);
while (x > 0) {
printf("%llu\n",(a + b));
x = scanf("%llu%llu" ,&a, &b);
}
return 0;
}
You cannot use regular arithmetic types for this, even unsigned long long only has 64 bits which is much less than required for your purpose.
Also note that your loop test is incorrect: it should be while (x == 2)
Here is a small program that can handle numbers with 99 decimal digits:
#include <stdio.h>
#include <string.h>
char *bigadd(char *c, const char *a, const char *b) {
size_t alen = strlen(a);
size_t blen = strlen(b);
size_t clen = (alen > blen) ? alen : blen;
size_t i = clen;
int digit, carry = 0;
c[i] = '\0';
while (i > 0) {
digit = ((alen ? a[--alen] - '0' : 0) +
(blen ? b[--blen] - '0' : 0) +
carry);
carry = digit >= 10;
c[--i] = (char)('0' + (digit - carry * 10));
}
if (carry) {
memmove(c + 1, c, clen + 1);
c[0] = '1';
}
return c;
}
int main(int argc, char *argv[]) {
char a[100], b[100], c[101];
while (scanf("%99s%99s", a, b) == 2) {
printf("%s\n", bigadd(c, a, b));
}
return 0;
}
Try a bignum library such as GMP. Here's an example.
#include <gmp.h>
#include <stdio.h>
#include <assert.h>
int main(){
char inputStr[1024];
/*
mpz_t is the type defined for GMP integers.
It is a pointer to the internals of the GMP integer data structure
*/
mpz_t n;
int flag;
printf ("Enter your number: ");
scanf("%1023s" , inputStr); /* NOTE: never every write a call scanf ("%s", inputStr);
You are leaving a security hole in your code. */
/* 1. Initialize the number */
mpz_init(n);
mpz_set_ui(n,0);
/* 2. Parse the input string as a base 10 number */
flag = mpz_set_str(n,inputStr, 10);
assert (flag == 0); /* If flag is not 0 then the operation failed */
/* Print n */
printf ("n = ");
mpz_out_str(stdout,10,n);
printf ("\n");
/* 3. Add one to the number */
mpz_add_ui(n,n,1); /* n = n + 1 */
/* 4. Print the result */
printf (" n +1 = ");
mpz_out_str(stdout,10,n);
printf ("\n");
/* 5. Square n+1 */
mpz_mul(n,n,n); /* n = n * n */
printf (" (n +1)^2 = ");
mpz_out_str(stdout,10,n);
printf ("\n");
/* 6. Clean up the mpz_t handles or else we will leak memory */
mpz_clear(n);
}

Parsing a string into an array of integers in C

So now that I've figured out how to get what I want, I'm just hoping somebody can let me know a cleaner, less ridiculous way of achieving the same thing. I'm just learning C. Here was my approach.
int main()
{
// String of positive and negative integer values
// Numbers are never more than 2 digits
char TEMPS[256] = "1 -22 -8 14 5";
int N = 5;
int ints[N];
int i = 0;
int mult;
// Arbitrary number to identify that num is not yet in use
int num = 999;
int c = 0;
mult = (TEMPS[c] != 45) ? -1 : 1;
while(strcmp(&TEMPS[c], "\0") != 0)
{
if(TEMPS[c] == 32)
{
ints[i] = mult * num;
i++;
num = 999;
mult = (TEMPS[c + 1] == 45) ? -1 : 1;
}
else if((TEMPS[c] != 45) && (TEMPS[c] != 32))
{
if(num == 999)
{
num = TEMPS[c] - '0';
}
else
{
num = num * 10 + (TEMPS[c] - '0');
}
}
c++;
}
ints[i] = mult * num;
}
I would use strtol - here's a good site for how it works and examples
http://www.tutorialspoint.com/c_standard_library/c_function_strtol.htm
long int strtol(const char *str, char **endptr, int base)
Parameters
str -- This is the string containing the representation of an integral number.
endptr -- This is the reference to an object of type char*, whose value is set by the function to the next character in str after the numerical value.
base -- This is the base, which must be between 2 and 36 inclusive, or be the special value 0.
Return Value
This function returns the converted integral number as a long int value, else zero value is r
I've included one example from the site.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str[30] = "2030300 This is test";
char *ptr;
long ret;
ret = strtol(str, &ptr, 10);
printf("The number(unsigned long integer) is %ld\n", ret);
printf("String part is |%s|", ptr);
return(0);
}

print double in scientific format with no integer part

A simple problem but I can't get documentation about this kind of format: I want to print a float in a Fortran scientific notation, with its integer part always being zero.
printf("%0.5E",data); // Gives 2.74600E+02
I want to print it like this:
.27460E+03
How can I get this result as clean as possible?
If you only care about the integer part being 0 and not really leaving out the 0, i.e. if you're fine with 0.27460E+03 instead of .27460E+03 you could do something similar to this:
#include <stdio.h>
#include <stdlib.h>
void fortran_printf();
int main(void)
{
double num = 274.600;
fortran_printf(num);
exit(EXIT_SUCCESS);
}
void fortran_printf(double num)
{
int num_e = 0;
while (num > 1.0) {
num /= 10;
num_e++;
}
printf("%.5fE+%02d", num, num_e);
}
Otherwise you have to take a detour over strings. Note that the code above is only meant to get you started. It certainly doesn't handle any involved cases.
I tried doing this with log10() and pow(), but ended up having problems with rounding errors. So as commented by #Karoly Horvath, string manipulation is probably the best approach.
#include <stdlib.h>
char *fortran_sprintf_double(double x, int ndigits) {
char format[30], *p;
static char output[30];
/* Create format string (constrain number of digits to range 1–15) */
if (ndigits > 15) ndigits = 15;
if (ndigits < 1) ndigits = 1;
sprintf(format, "%%#.%dE", ndigits-1);
/* Convert number to exponential format (multiply by 10) */
sprintf(output, format, x * 10.0);
/* Move the decimal point one place to the left (divide by 10) */
for (p=output+1; *p; p++) {
if (*p=='.') {
*p = p[-1];
p[-1] = '.';
break;
}
}
return output;
}
A string manipulation approach:
int printf_NoIntegerPart(double x, int prec) {
char buf[20 + prec];
sprintf(buf, "%+.*E", prec - 1, x * 10.0); // use + for consistent width output
if (buf[2] == '.') {
buf[2] = buf[1];
buf[1] = '.';
}
puts(buf);
}
int main(void) {
printf_NoIntegerPart(2.74600E+02, 5); // --> +.27460E+03
}
This will print "INF" for |x| > DBL_MAX/10
printf() will not meet OP’s goal in one step using some special format. Using sprintf() to form the initial textual result is a good first step, care must be exercised when trying to do “math” with string manipulation.
Akin to #user3121023 deleted answer.
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
int printf_NoIntegerPart(double x, int prec) {
assert(prec >= 2 && prec <= 100);
char buffer[prec + 16]; // Form a large enough buffer.
sprintf(buffer, "%.*E", prec - 1, x);
int dp = '.'; // Could expand code here to get current local's decimal point.
char *dp_ptr = strchr(buffer, dp);
char *E_ptr = strchr(buffer, 'E');
// Insure we are not dealing with infinity, Nan, just the expected format.
if (dp_ptr && dp_ptr > buffer && E_ptr) {
// Swap dp and leading digit
dp_ptr[0] = dp_ptr[-1];
dp_ptr[-1] = dp;
// If x was not zero …
if (x != 0) {
int expo = atoi(&E_ptr[1]); // Could use `strtol()`
sprintf(&E_ptr[1], "%+.02d", expo + 1);
}
}
return puts(buffer);
}
int main(void) {
printf_NoIntegerPart(2.74600E+02, 5); // ".27460E+03"
return 0;
}
Faced same issue while fortran porting.
DId not found std C format :(
Implemented both approaches - with log10/pow and with string manipulation.
#include <ansi_c.h>
#define BUFFL 16
// using log10 , 3 digits after "."
char* fformat1(char* b, double a) {
int sign = 1;
double mant;
double order;
int ord_p1;
if (a<0) {
sign =-1;
a = -a;
}
order=log10 (a);
if (order >=0) ord_p1 = (int) order +1; // due sto property of int
else ord_p1 = (int) order;
mant=a/(pow(10,ord_p1));
sprintf(b,"%.3fE%+03d",mant,ord_p1);
if (sign==-1) b[0]='-';
return b;
}
// using string manipulation
char* fformat2(char* b, double a) {;
int sign = 1;
int i;
int N=3;
if (a<0) {
sign =-1;
a = -a;
}
sprintf(b,"%0.3E",a*10); // remember - we *10 to have right exponent
b[1]=b[0]; // 3.123 => .3123
b[0]='.';
for (i=N; i>=0; i--) // and shif all left
b[i+1]=b[i];
b[0]='0'; // pad with zero 0.312
if (sign==-1) b[0]='-'; // sign if needed
return b;
}
int main () {
char b1[BUFFL]; // allocate buffer outside.
char b2[BUFFL];
char b3[BUFFL];
char b4[BUFFL];
char b5[BUFFL];
printf("%s %s %s %s %s \n", fformat(b1,3.1), fformat(b2,-3.0), fformat(b3,3300.),
fformat(b4,0.03), fformat(b5,-0.000221));
printf("%s %s %s %s %s \n", fformat2(b1,3.1), fformat2(b2,-3.0), fformat2(b3,3300.),
fformat2(b4,0.03), fformat2(b5,-0.000221));
return 1;
}

Algorithm to parse an int from a string in one pass

I'm trying to write a function that parses an integer from a string representation.
My problem is that I don't know how to do this with one pass through the string. If I knew ahead of time that the input contained only characters in the range '0', '1', ..., '9' and that the string was of length n, I could of course calculate
character_1 * 10^(n-1) + character_2 * 10^(n-2) + .... + character_n * 10^0
but I want to deal with the general scenario as I've presented it.
I'm not looking for a library function, but an algorithm to achieve this in "pure C".
Here's the code I started from:
int parse_int (const char * c1, const char * c2, int * i)
{
/*
[c1, c2]: Range of characters in the string
i: Integer whose string representnation will be converted
Returns the number of characters parsed.
Exs. "2342kjsd32" returns 4, since the first 4 characters were parsed.
"hhsd3b23" returns 0
*/
int n = 0;
*i = 0;
while (c1!= c2)
{
char c = *c1;
if (c >= '0' && c <= '9')
{
}
}
return n;
}
Just as some of the comments and answers suggested, maybe a bit clearer: You have to "shift" the result "left" by multiplying it by 10 in every iteration before the addition of the new digit.
Indeed, this should remind us of Horner's method. As you have recognized, the result can be written like a polynomial:
result = c1 * 10^(n-1) + c2 * 10^(n-2) + ... + cn * 10^0
And this equation can be rewritten as this:
result = cn + 10*(... + 10*(c2 + 10*c1))
Which is the form this approach is based on. From the formula you can already see, that you don't need to know the power of 10 the first digit is to be multiplied by, directly from the start.
Here's an example:
#include <stdio.h>
int parse_int(const char * begin, const char * end, int * result) {
int d = 0;
for (*result = 0; begin != end; d++, begin++) {
int digit = *begin - '0';
if (digit >= 0 && digit < 10) {
*result *= 10;
*result += digit;
}
else break;
}
return d;
}
int main() {
char arr[] = "2342kjsd32";
int result;
int ndigits = parse_int(arr, arr+sizeof(arr), &result);
printf("%d digits parsed, got: %d\n", ndigits, result);
return 0;
}
The same can be achieved using sscanf(), for everyone that is fine with using the C standard library (can also handle negative numbers):
#include <stdio.h>
int main() {
char arr[] = "2342kjsd32";
int result, ndigits;
sscanf(arr, "%d%n", &result, &ndigits);
printf("%d digits parsed, got: %d\n", ndigits, result);
return 0;
}
The output is (both implementations):
$ gcc test.c && ./a.out
4 digits parsed, got: 2342
I think this is good solution to count parse character
int parse(char *str)
{
int k = 0;
while(*str)
{
if((*str >= '0') & (*str <= '9'))
break;
str++;
k++;
}
return k;
}
Here's a working version:
#include <stdio.h>
int parse_int (const char * c1, const char * c2, int * i)
{
/*
[c1, c2]: Range of characters in the string
i: Integer whose string representnation will be converted
Returns the number of characters parsed.
Exs. "2342kjsd32" returns 4, since the first 4 characters were parsed.
"hhsd3b23" returns 0
*/
int n = 0;
*i = 0;
for (; c1 != c2; c1++)
{
char c = *c1;
if (c >= '0' && c <= '9')
{
++n;
*i = *i * 10 + c - '0';
}
else
{
break;
}
}
return n;
}
int main()
{
int i;
char const* c1 = "2342kjsd32";
int n = parse_int(c1, c1+10, &i);
printf("n: %d, i: %d\n", n, i);
return 0;
}
Output:
n: 4, i: 2342

Resources