How to extract multiple numbers from string in C - c

I have a question. If I want to extract more than one float number in a string what should I do ?
I know that there are functions like strtof by which I can extract the number. The question is what if there are more than one number existing in string?
I just want and I know that only thing that is needed is pointer to the next character after finding the number. Then continue searching until it reaches \n but how?
EXAMPLE:
Imagine I have a report about rainfall of some towns during a year and I want to
extract rainfall for each town (when it gets to the \nreport for the town is finished ).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv)
{
char* data = "Rome:Jan 81.2,Feb 63.2,Mar 70.3,Apr 55.7,May 53.0,Jun 36.4,Jul 17.5,Aug 27.5,Sep 60.9,Oct 117.7,Nov 111.0,Dec 97.9\n"
"London:Jan 48.0,Feb 38.9,Mar 39.9,Apr 42.2,May 47.3,Jun 52.1,Jul 59.5,Aug 57.2,Sep 55.4,Oct 62.0,Nov 59.0,Dec 52.9\n"
"Paris:Jan 182.3,Feb 120.6,Mar 158.1,Apr 204.9,May 323.1,Jun 300.5,Jul 236.8,Aug 192.9,Sep 66.3,Oct 63.3,Nov 83.2,Dec 154.7\n"
"NY:Jan 108.7,Feb 101.8,Mar 131.9,Apr 93.5,May 98.8,Jun 93.6,Jul 102.2,Aug 131.8,Sep 92.0,Oct 82.3,Nov 107.8,Dec 94.2\n"
"Vancouver:Jan 145.7,Feb 121.4,Mar 102.3,Apr 69.2,May 55.8,Jun 47.1,Jul 31.3,Aug 37.0,Sep 59.6,Oct 116.3,Nov 154.6,Dec 171.5\n"
"Sydney:Jan 103.4,Feb 111.0,Mar 131.3,Apr 129.7,May 123.0,Jun 129.2,Jul 102.8,Aug 80.3,Sep 69.3,Oct 82.6,Nov 81.4,Dec 78.2\n"
"Bangkok:Jan 10.6,Feb 28.2,Mar 30.7,Apr 71.8,May 189.4,Jun 151.7,Jul 158.2,Aug 187.0,Sep 319.9,Oct 230.8,Nov 57.3,Dec 9.4\n"
"Tokyo:Jan 49.9,Feb 71.5,Mar 106.4,Apr 129.2,May 144.0,Jun 176.0,Jul 135.6,Aug 148.5,Sep 216.4,Oct 194.1,Nov 95.6,Dec 54.4\n"
"Beijing:Jan 3.9,Feb 4.7,Mar 8.2,Apr 18.4,May 33.0,Jun 78.1,Jul 224.3,Aug 170.0,Sep 58.4,Oct 18.0,Nov 9.3,Dec 2.7\n"
"Lima:Jan 1.2,Feb 0.9,Mar 0.7,Apr 0.4,May 0.6,Jun 1.8,Jul 4.4,Aug 3.1,Sep 3.3,Oct 1.7,Nov 0.5,Dec 0.7";
const char* towns[14] = {"Rome", "London", "Paris", "NY", "Vancouver", "Sydney", "Bangkok", "Tokyo",
"Beijing", "Lima", "Montevideo", "Caracas", "Madrid", "Berlin"};
size_t i = 0;
float nums[12];
char *ch_ptr = strstr(data,towns[0]); //pointing to first character
const char *stop ="\n";
while((ch_ptr++) != stop)
{
nums[i] = strtof(); ///How should I do it ????
i++;
}
return 0;
}

Using two nested for loops, the float value for each town and month can be captured.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv)
{
char* data = "Rome:Jan 81.2,Feb 63.2,Mar 70.3,Apr 55.7,May 53.0,Jun 36.4,Jul 17.5,Aug 27.5,Sep 60.9,Oct 117.7,Nov 111.0,Dec 97.9\n"
"London:Jan 48.0,Feb 38.9,Mar 39.9,Apr 42.2,May 47.3,Jun 52.1,Jul 59.5,Aug 57.2,Sep 55.4,Oct 62.0,Nov 59.0,Dec 52.9\n"
"Paris:Jan 182.3,Feb 120.6,Mar 158.1,Apr 204.9,May 323.1,Jun 300.5,Jul 236.8,Aug 192.9,Sep 66.3,Oct 63.3,Nov 83.2,Dec 154.7\n"
"NY:Jan 108.7,Feb 101.8,Mar 131.9,Apr 93.5,May 98.8,Jun 93.6,Jul 102.2,Aug 131.8,Sep 92.0,Oct 82.3,Nov 107.8,Dec 94.2\n"
"Vancouver:Jan 145.7,Feb 121.4,Mar 102.3,Apr 69.2,May 55.8,Jun 47.1,Jul 31.3,Aug 37.0,Sep 59.6,Oct 116.3,Nov 154.6,Dec 171.5\n"
"Sydney:Jan 103.4,Feb 111.0,Mar 131.3,Apr 129.7,May 123.0,Jun 129.2,Jul 102.8,Aug 80.3,Sep 69.3,Oct 82.6,Nov 81.4,Dec 78.2\n"
"Bangkok:Jan 10.6,Feb 28.2,Mar 30.7,Apr 71.8,May 189.4,Jun 151.7,Jul 158.2,Aug 187.0,Sep 319.9,Oct 230.8,Nov 57.3,Dec 9.4\n"
"Tokyo:Jan 49.9,Feb 71.5,Mar 106.4,Apr 129.2,May 144.0,Jun 176.0,Jul 135.6,Aug 148.5,Sep 216.4,Oct 194.1,Nov 95.6,Dec 54.4\n"
"Beijing:Jan 3.9,Feb 4.7,Mar 8.2,Apr 18.4,May 33.0,Jun 78.1,Jul 224.3,Aug 170.0,Sep 58.4,Oct 18.0,Nov 9.3,Dec 2.7\n"
"Lima:Jan 1.2,Feb 0.9,Mar 0.7,Apr 0.4,May 0.6,Jun 1.8,Jul 4.4,Aug 3.1,Sep 3.3,Oct 1.7,Nov 0.5,Dec 0.7";
const char* months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun"
, "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
const char* towns[14] = {"Rome", "London", "Paris", "NY", "Vancouver", "Sydney", "Bangkok", "Tokyo",
"Beijing", "Lima", "Montevideo", "Caracas", "Madrid", "Berlin"};
size_t i = 0;
float nums[12];
char *end = NULL;
char *town_ptr = NULL;
char *month_ptr = NULL;
char monthid[100] = "";
char townid[100] = "";
for ( int town = 0; town < 14; town++)
{
if ( ( town_ptr = strstr ( data, towns[town]))) {
i = 0;
sscanf ( town_ptr, "%99[^:]", townid);
for ( int month = 0; month < 12; month++)
{
if ( ( month_ptr = strstr ( town_ptr, months[month]))) {
sscanf ( month_ptr, "%99s", monthid);
month_ptr += strlen ( months[month]);
nums[i] = strtof( month_ptr, &end);
if ( *end == ',' || *end == '\n' || *end == '\0') {
printf ( "%s %s nums[%d] = %f\n", townid, monthid, i, nums[i]);
i++;
}
}
}
}
}
return 0;
}
To parse from the town name to a newline. If a month was missing from a town, the previous code would use the month from the next town. This will iterate from the town name until twelve values, a newline, a '\0' or failure to parse a double.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv)
{
char* data = "Rome:Jan 81.2,Feb 63.2,Mar 70.3,Apr 55.7,May 53.0,Jun 36.4,Jul 17.5,Aug 27.5,Sep 60.9,Oct 117.7,Nov 111.0,Dec 97.9\n"
"London:Jan 48.0,Feb 38.9,Mar 39.9,Apr 42.2,May 47.3,Jun 52.1,Jul 59.5,Aug 57.2,Sep 55.4,Oct 62.0,Nov 59.0,Dec 52.9\n"
"Paris:Jan 182.3,Feb 120.6,Mar 158.1,Apr 204.9,May 323.1,Jun 300.5,Jul 236.8,Aug 192.9,Sep 66.3,Oct 63.3,Nov 83.2,Dec 154.7\n"
"NY:Jan 108.7,Feb 101.8,Mar 131.9,Apr 93.5,May 98.8,Jun 93.6,Jul 102.2,Aug 131.8,Sep 92.0,Oct 82.3,Nov 107.8,Dec 94.2\n"
"Vancouver:Jan 145.7,Feb 121.4,Mar 102.3,Apr 69.2,May 55.8,Jun 47.1,Jul 31.3,Aug 37.0,Sep 59.6,Oct 116.3,Nov 154.6,Dec 171.5\n"
"Sydney:Jan 103.4,Feb 111.0,Mar 131.3,Apr 129.7,May 123.0,Jun 129.2,Jul 102.8,Aug 80.3,Sep 69.3,Oct 82.6,Nov 81.4,Dec 78.2\n"
"Bangkok:Jan 10.6,Feb 28.2,Mar 30.7,Apr 71.8,May 189.4,Jun 151.7,Jul 158.2,Aug 187.0,Sep 319.9,Oct 230.8,Nov 57.3,Dec 9.4\n"
"Tokyo:Jan 49.9,Feb 71.5,Mar 106.4,Apr 129.2,May 144.0,Jun 176.0,Jul 135.6,Aug 148.5,Sep 216.4,Oct 194.1,Nov 95.6,Dec 54.4\n"
"Beijing:Jan 3.9,Feb 4.7,Mar 8.2,Apr 18.4,May 33.0,Jun 78.1,Jul 224.3,Aug 170.0,Sep 58.4,Oct 18.0,Nov 9.3,Dec 2.7\n"
"Lima:Jan 1.2,Feb 0.9,Mar 0.7,Apr 0.4,May 0.6,Jun 1.8,Jul 4.4,Aug 3.1,Sep 3.3,Oct 1.7,Nov 0.5,Dec 0.7";
const char* towns[14] = {"Rome", "London", "Paris", "NY", "Vancouver", "Sydney", "Bangkok", "Tokyo",
"Beijing", "Lima", "Montevideo", "Caracas", "Madrid", "Berlin"};
float nums[12];
char *end = NULL;
char *town_ptr = NULL;
char monthid[100] = "";
char townid[100] = "";
int span = 0;
for ( int town = 0; town < 14; town++)
{
if ( ( town_ptr = strstr ( data, towns[town]))) {//find the town name
sscanf ( town_ptr, "%99[^:]:%n", townid, &span);
int each = 0;
town_ptr += span;
do {
sscanf ( town_ptr, "%s%n", monthid, &span);
town_ptr += span;
nums[each] = strtod ( town_ptr, &end);
if ( end == town_ptr) {//failed to parse a double
break;
}
printf ( "%s %s nums[%d] = %f\n", townid, monthid, each, nums[each]);
town_ptr = end + 1;//to advance past the comma
each++;
} while ( each < 12 && *end != '\0' && *end != '\n');
}
}
return 0;
}

Related

Call C function with arguments on fastcgi web application

I'm developing a web app for a reservation system and so far I achieved to send a mail with libcurl and display the form in HTML using fcgi_stdio.h, but both separately.
This is how it looks
#define __USE_XOPEN
#define _GNU_SOURCE
#include <stdio.h>
#include <fcgi_stdio.h>
#include <string.h>
#include <stdlib.h>
#include "mail.h"
#include "booking.h"
int
main()
{
char to[20], name[20];
//char *year, *mon, *day, *hour, *min;
char date[20];
char num_guest[4], phone[10];
while (FCGI_Accept() >= 0) {
printf("Content-type: text/html\n\n");
printf("<h1>Welcome</h1>");
char *method = getenv("REQUEST_METHOD");
char form[2048] = {0};
char output[2048] = {0};
if(strcmp(method, "GET") == 0) {
strcpy(form,
"<form method='POST' action=''>"
"<input id='name' name='name' type='text'></input>"
"<br>"
"<input id='to' name='to' type='email'></input>"
"<br>"
"<input id='date' type='datetime-local' name='date' />"
"<br>"
"<input type='tel' "
"id='phone' name='phone' size='20' "
"minlenght='9' maxlenght='14' required>"
"<br>"
"<input type='number' id='num_guest' name='num_guest'"
"min='1' max='18'>"
"<br>"
"<input type='submit' value='Submit'>"
"</form>"
);
} else if (strcmp(method, "POST") == 0) {
int ilen = atoi(getenv("CONTENT_LENGTH"));
//char *bufp = malloc(ilen);
char *bufp = (char *) malloc(ilen * sizeof(char));
fread(bufp, ilen, 1, stdin);
printf("<h3>Thank you for your reservation!</h3>");
strcpy(output, bufp);
free(bufp);
/* declare data variables */
sscanf(output,
"name=%[^&]&to=%[^&]&date=%[^&]&phone=%[^&]&num_guest=%[^&]",
name, to, date, phone, num_guest);
replace(date, "%3A", ":"); // makes the date readable
replace(to, "%40", "#"); // makes the mail readable
}
printf(
"<div>"
"%s"
"</div>",
form
);
}
return 0;
}
The code above works fine, but I would like to call these functions after clicking the Submit button.
book_for(to, name, num_guest, phone, date);
send_mail("addr", "confirmation.mail");
Those functions alone and declaring before the arguments as char *name = 'some name'; work fine too sending the mail to the recipient.
Thanks for your help :)

PQexecParams() returning ERROR: invalid input syntax for type date: ""

If fr_dt is empty - PQresultErrorMessage() return "ERROR: invalid input syntax for type date: """
My c code:
string new_data = "some new data";
string fr_dt = obj.getDate();
const char *c_new_data = new_data.c_str();
const char *c_fr_dt = fr_dt.c_str();
const char* ins_data_com = "select * from ins_data($1,$2);
int nParams = 2;
const char *const paramValues[] = {c_new_data,c_fr_dt};
const int paramLengths[] = {sizeof(c_new_data),sizeof(c_fr_dt)};
const int paramFormats[] = {0,0};
int resultFormat = 0;
PGresult res_com = PQexecParams(conn,ins_data_com,
nParams, NULL, paramValues, paramLengths, paramFormats, resultFormat);
and pgsql code:
CREATE OR REPLACE FUNCTION ins_data(in_data text, in_date date)
RETURNS int
LANGUAGE plpgsql
AS $function$
DECLARE n_id int;
BEGIN
WITH cte AS (
INSERT INTO public.my_table
(new_data, time_in)
VALUES(in_data, coalesce(in_date::timestamp,current_timestamp))
RETURNING id AS new_id
)
SELECT new_id INTO n_id FROM cte;
RETURN n_id;
END;
$function$
;
How can I fix it?
Solution:
const char *с_fr_dt = NULL;
if (!fr_dt.empty()) {
с_fr_dt = fr_dt.c_str();
}

How to make an array of character in C

I am trying to make an array of character. I get this code and get error
#include<stdio.h>
#include<stdlib.h>
#include"boolean.h"
const char *skillNames[8];
skillNames[0] = "Darth Vader";
skillNames[1] = "Han Solo";
skillNames[2] = "Master Yoda";
skillNames[3] = "Luke Skywalker";
skillNames[4] = "Obi Wan Kenobi";
skillNames[5] = "Chewbacca";
skillNames[6] = "Emperor Palpatine";
skillNames[7] = "Princess Leia";
#include<stdio.h>
#include<stdlib.h>
#include"boolean.h"
int main() {
const char *skillNames[8];
skillNames[0] = "Darth Vader";
skillNames[1] = "Han Solo";
skillNames[2] = "Master Yoda";
skillNames[3] = "Luke Skywalker";
skillNames[4] = "Obi Wan Kenobi";
skillNames[5] = "Chewbacca";
skillNames[6] = "Emperor Palpatine";
skillNames[7] = "Princess Leia";
}
Put it inside a main function.
You can use the initialization syntax. You don't even need to mention the size of the array:
const char *skillNames[] = {
"Darth Vader", "Han Solo", "Master Yoda", "Luke Skywalker",
"Obi Wan Kenobi", "Chewbacca", "Emperor Palpatine", "Princess Leia",
};
Add a main() function and replace the #include"boolean.h" with #include<stdbool.h>. See if that fixes the error or not.
The full code can be like this:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main()
{
const char *skillNames[8];
skillNames[0] = "Darth Vader";
skillNames[1] = "Han Solo";
skillNames[2] = "Master Yoda";
skillNames[3] = "Luke Skywalker";
skillNames[4] = "Obi Wan Kenobi";
skillNames[5] = "Chewbacca";
skillNames[6] = "Emperor Palpatine";
skillNames[7] = "Princess Leia";
}

How to get and manipulate text between two special charters?

Hi *John* We wish you* Happy Birthday * and blah blah blah..
Ho can I get text between each pair of * and return like
Hi <b>john</b> We wish you <b> Happy Birthday </b> and blah blah blah..
You can use this regexp /\*([^\*]+)\*/g
const regex = /\*([^\*]+)\*/g;
const str = `Hi *John* We wish you* Happy Birthday * and blah blah blah..`;
const subst = `<b>$1</b>`;
// The substituted value will be contained in the result variable
const result = str.replace(regex, subst);
console.log('Substitution result: ', result);
As a function
const str = `Hi *John* We wish you* Happy Birthday * and blah blah blah..`;
function bold(str) {
const regex = /\*([^\*]+)\*/g;
const subst = `<b>$1</b>`;
// The substituted value will be contained in the returned variable
return str.replace(regex, subst);
}
const result = bold(str);
console.log('Substitution result: ', result);
I think this will solve your problem.
str = "Hi *John* We wish you* Happy Birthday * and blah blah blah..";
replaceInStr(str, "<b>");
function replaceInStr(str, replace) {
str = str.replace(/\*/, replace);
if(replace === "<b>") {
replace = "</b>";
} else {
replace = "<b>";
}
if(str.search(/\*/) !== -1) {
replaceInStr(str, replace);
} else {
console.log(str);
}
}
you can use like this
var stringArray = str.split("*");
var stringOut = "";
for (var i = 0 ; i < stringArray.length; i++) {
stringOut += stringArray[i];
if (i % 2 !== 0) {
stringOut += "</br>";
}
else
{
stringOut += "<br>";
}
}
Try this :
var txt = "Hi *John* We wish you* Happy Birthday * and blah blah blah..";
txt = txt.replace(/\*(.*?)\*/g, "<b>$1</b>");
console.log(txt);

Why are Go's strings.Fields(str) and strings.Split(str, " ") so slow?

I have been testing functions in Node and Go to compare their performance. In almost every test, Go is much faster than Node, except when strings.Fields() or strings.Split() is used, then Node is 2-3 times as fast.
Go (2.14s):
start := time.Now()
var newWords []string
str := "asd asjhfa lsjdhalsdjhfa dhfald hfaljdh faldhfasjdhfalsdh asd alsdh alksdh alksdh alksd alkjsd fadlkj dalkjdh asdhfef afa d6a 5a85dfa s5da5d ad a6sd58ad5a8sd5f 8as5f as5 a8s5 8as6d5 8asd65f8as6d58 a5sd 8a5ds8f7 a6s5d"
for j := 0; j < 1000000; j++ {
words := strings.Split(str, " ")
wordsLen := len(words)
newWords = nil
for i := 0; i < wordsLen; i++ {
if words[i][:1] != "s" {
newWords = append(newWords, words[i])
}
}
}
dur := time.Since(start)
fmt.Println(newWords)
fmt.Println(dur)
Node (847ms):
let start = new Date()
let newWords = []
let str = "asd asjhfa lsjdhalsdjhfa dhfald hfaljdh faldhfasjdhfalsdh asd alsdh alksdh alksdh alksd alkjsd fadlkj dalkjdh asdhfef afa d6a 5a85dfa s5da5d ad a6sd58ad5a8sd5f 8as5f as5 a8s5 8as6d5 8asd65f8as6d58 a5sd 8a5ds8f7 a6s5d"
for (let j = 0; j < 1000000; j++) {
let words = str.split(' ')
let wordsLen = words.length
newWords = []
for (let i = wordsLen - 1; i >= 0; i--) {
if (words[i].substr(0, 1) !== 's') {
newWords.push(words[i])
}
}
}
console.log((new Date() - start) + 'ms')
First, let's run your tests.
$ go run travis.go
5.892531292s
$ node travis.js
4065ms
$
Go 5.89 seconds versus Node.js 4.07 seconds.
Second, let's run a Go benchmark and see what you are really doing. It's a lot more than the strings.Fields(str) or strings.Split(str, " ") that you said in your original post.
travis_test.go:
package main
import (
"strings"
"testing"
)
var str = "asd asjhfa lsjdhalsdjhfa dhfald hfaljdh faldhfasjdhfalsdh asd alsdh alksdh alksdh alksd alkjsd fadlkj dalkjdh asdhfef afa d6a 5a85dfa s5da5d ad a6sd58ad5a8sd5f 8as5f as5 a8s5 8as6d5 8asd65f8as6d58 a5sd 8a5ds8f7 a6s5d"
func Travis() {
var newWords []string
for j := 0; j < 1000000; j++ {
words := strings.Split(str, " ")
wordsLen := len(words)
newWords = nil
for i := 0; i < wordsLen; i++ {
if words[i][:1] != "s" {
newWords = append(newWords, words[i])
}
}
}
}
func BenchmarkTravis(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
Travis()
}
b.StopTimer()
}
Output:
$ go test -run=! -bench=Travis travis_test.go
goos: linux
goarch: amd64
BenchmarkTravis-4 1 5832192616 ns/op 1488002816 B/op 7000015 allocs/op
PASS
ok command-line-arguments 5.838s
$

Resources