how to overcome a parsing error in SSCANF function in Clanguage? - c

how to parse a empty substring with sscanf.......
if my string str[]="is first,,third,final." i cannot able to read the third and final substring if my second substring is zero. Is there an solution to overcome this error.....?????
**Code:**
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
char *tokenstring = "first,second,25.5,15";
int result, i;
double fp;
char o[10], f[10], s[10], t[10];
void main()
{
result = sscanf(tokenstring,"%[^','],%[^','],%[^','],%s", o,t,s,f);`sscanf function`
fp = atof(s);
i = atoi(f);
printf("%s\n %lf\n %s\n %d\n", o,t,fp,i);
}
for this program if i execute my output is
`output`
>first
>second
>25.5
>15
but if i try to remove the substring "second" in the tokenstring pointer... and if i try to execute, then i get output as:
char *tokenstring = "first,,25.5,15";
>first
>(blank)
>0.00
>0
how do i read the third and fourth substring in the string"tokenstring"...any suggestions ?????????? .

Parse the input character-by-character
char part[4][1000] = {0};
const char *input = "first,,25.5,15";
size_t k, n;
for (k = 0; k < 4; k++) {
char *curr = part[k];
while (*input && *input != ',') {
*curr++ = *input++;
}
if (*input == ',') input++; else break;
}
/* (k+1) elements have been parsed */
for (n = 0; n < k + 1; n++) {
printf("part %d (between square parenthesis): [%s]\n", (int)n, part[n]);
}

Related

Not getting output from string array function in c

I was making a split function in C to use its return value in some programs. But when I checked its value using printf, I discovered that there are some errors but I was unable to fix them myself. I fixed most of the errors I could.
The code I wrote is:
#include <stdio.h>
#include <string.h>
char **split(char *token, char *delimiter, int *a[], int *size_of_a) {
int i = 0;
char **final_result;
char *str = strtok(token, delimiter);
while (str != NULL) {
*a[i] = strlen(str); //maybe one of the errors but I don't know how to fix it
//even after removing a[i] by backslash and changing it in loop and main, there is still no output received in main
getch();
for (int j = 0; j < *a[i]; j++) {
final_result[i][j] = str[j];
}
str = strtok(NULL, delimiter);
i++;
}
*size_of_a = i;
return final_result;
}
int main() {
char *parameter_1;
char *parameter_2;
int *size_1;
int size_2;
printf("Enter the token: ");
scanf("%s", &parameter_1);
printf("\nEnter the delimiter: ");
scanf("%s", &parameter_2);
char **result_2 = split(parameter_1, parameter_2, &size_1, &size_2);
printf("\nThe result is:");
for (int x = 0; x < size_2; x++) {
printf('\n');
for (int y = 0; y < size_1[x]; y++) {
printf("%c", result_2[x][y]);
}
}
getch();
return 0;
}
How can I fix the output error?
There are multiple problems in the code:
You do not allocate space for the array of pointers: final_result is uninitialized, storing anything via dereferencing it has undefined behavior, most likely a segmentation fault.
You should use strcpn() and strspn() to compute the number of tokens, allocate the array with or without an extra slot for a NULL terminator and perform a second phase splitting the tokens and storing the pointers to the array. You might want to store copies of the tokens to avoid modifying the original string that may be constant or go out of scope.
printf('\n'); is invalid: you must pass a string, not a character constant.
scanf("%s", &parameter_1); also has undefined behavior: you pass the address of a pointer instead of a pointer to an array of char.
Here is a modified version:
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _MSC_VER
// define POSIX function strndup if not available
char *strndup(const char *s, size_t n) {
size_t len;
for (len = 0; len < n && s[len]; len++)
continue;
char *ptr = malloc(len + 1);
if (ptr) {
memcpy(ptr, s, len);
ptr[len] = '\0';
}
return ptr;
}
#endif
char **split(const char *str, const char *delimiters, int **a, int *size_of_a) {
int i, count, len;
char **final_result;
const char *p;
// phase 1: count the number of tokens
p = str + strspn(str, delimiters);
for (count = 0; *p; count++) {
p += strcspn(p, delimiters);
p += strspn(p, delimiters);
}
// phase 2: allocate the arrays
final_result = calloc(sizeof(*final_result), count + 1);
if (a) {
*a = calloc(sizeof(**a), count);
}
if (size_of_a) {
*size_of_a = count;
}
// phase 3: copy the tokens
p = str;
for (i = 0; i < count; i++) {
p += strspn(p, delimiters); // skip the delimiters
len = strcspn(p, delimiters); // count the token length
if (a) {
(*a)[i] = len;
}
final_result[i] = strndup(p, len); // duplicate the token
p += len;
}
final_result[count] = 0;
return final_result;
}
// read and discard the rest of the user input line
int flush_input(void) {
int c;
while ((c = getchar()) != EOF && c != '\n')
continue;
return c;
}
int main() {
char buf[256];
char delimiters[20];
printf("Enter the string: ");
if (scanf("%255[^\n]", buf) != 1)
return 1;
flush_input();
printf("\nEnter the delimiters: ");
if (scanf("%19[^\n]", delimiters) != 1)
return 1;
flush_input();
int *sizes;
int count;
char **array = split(buf, delimiters, &sizes, &count);
printf("\nThe result is:\n");
for (int x = 0; x < count; x++) {
for (int y = 0; y < sizes[x]; y++) {
putchar(array[x][y]);
}
printf("\n");
}
getchar();
return 0;
}

How so separate a string and order each record by left number in C

I have a file.csv . it contains two numbers separated by a comma.I put every line , such as string, in a pointer of char char *arr. My aim is to sort in ascending order by left number (number before comma i.e. //this is the example of what I have to sort, the whole example is below:
9514902
1134289
7070279
ecc..)
I tried strtok() but it delete the number after comma. I need both of the numbers for each couple.
To order the numbers I used Insertion Sort, trasforming my strings (couple of numbers with comma for me is a string) in long integers in order to compare them. swap function doesn't work because it returns me numbers that I've never passed him.
How can I resolve it?
main.c
#define SIZE 10
#define LEN 20
void swap(char *xp, char *yp){
char *temp=xp;
*xp = *yp;
*yp = *temp;
}
int main(){
FILE *fd = NULL;
fd = fopen("file.csv", "r");
int pos=0;
char (*arr)[LEN] = NULL;
arr = calloc ( SIZE, sizeof *arr);
while ( pos < SIZE && fgets ( arr[pos], sizeof arr[pos], fd)) {
++pos;
}
int i, j;
char *ptr;
for (i = 1; i < SIZE; i++){
char *p = strtok(arr[i], ",");
long pivot= strtol(p,&ptr,10);
char * c = strtok(arr[i-1], ",");
long value= strtol(c,&ptr,10);
for (j = i - 1; (j >= 0) && (value>pivot); j--){
swap(arr[j],arr[j+1]);
j--;
c = strtok(arr[j], ",");
value= strtol(c,&ptr,10);
}
}
}
file.csv
9514902,846
1134289,572
7070279,994
30886,48552
750704,1169
1385812,729
471548,3595
8908491,196
4915590,362
375309,212
You can do it without strtok too, Maybe this is not you looking for but you can look as another way of doing what you want, Have Fun
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(){
FILE* pFile = fopen("file.csv", "r");
if(pFile == NULL)
return 1;
char aBuf[256];
char aResult[1024];
aResult[0] = '\0';
// get each line
for(int i=0; fgets(aBuf, sizeof(aBuf), pFile) != NULL; i++){
// find comma in line
for(int j=0; j < strlen(aBuf); j++){
if(aBuf[j] != ',')
continue;
// copy everything before comma
char aAnotherBuffer[50];
strncpy(aAnotherBuffer, aBuf, j);
// convert it to integer
int FirstNum = atoi(aAnotherBuffer);
// get after of comma and convert it too
int SecondNum = atoi(aBuf + j + 1);
// make line that with sorted values
char aRes[256];
sprintf(aRes,
"%d,%d\n",
FirstNum < SecondNum? FirstNum: SecondNum,
FirstNum > SecondNum? FirstNum: SecondNum
);
// concatenate to result buffer
strcat(aResult, aRes);
// go for next line
break;
}
}
fclose(pFile);
// save results
{
FILE* pResFile = fopen("result.csv", "w");
if(pResFile){
fputs(aResult, pResFile);
fclose(pResFile);
}
}
return 0;
}

Error when extracting sub-string from the start of source string in C

This is from an exercise in Chapter 9 of Programming in C 4th Edition. The programme is to read in characters into a string and extract a portion of the string into a sub-string by specifying a start position and number of characters.
The programme compiles and runs well except when the zeroth position of the source is stated as the start. Nothing is then displayed.
This is my code.
/* Programme to extract a portion from a string using function
sub-string (source, start, count, result) ex9.4.c
ALGORITHM
Get text input into a char array (declare to be fixed size);
Determine length of source string;
Prepare result array to be dynamic length using desired count + 1;
Copy from source array into result array
*/
#include <stdio.h>
#include <stdbool.h>
#define MAX 501
void read_Line (char buffer[]);
int string_Length (char string[]);
void sub_String (char source[], int start, int count, char result[]);
int main(void)
{
char strSource[MAX];
bool end_Of_Text = false;
int strCount = 0;
printf("This is a programme to extract a sub-string from a source string.\n");
printf("\nType in your text (up to 500 characters).\n");
printf("When you are done, press 'RETURN or ENTER'.\n\n");
while (! end_Of_Text)
{
read_Line(strSource);
if (strSource[0] == '\0')
{
end_Of_Text = true;
}
else
{
strCount += string_Length(strSource);
}
}
// Declare variables to store sub-string parameters
int subStart, subCount;
char subResult[MAX];
printf("Enter start position for sub-string: ");
scanf(" %i", &subStart);
getchar();
printf("Enter number of characters to extract: ");
scanf(" %i", &subCount);
getchar();
// Call sub-string function
sub_String(strSource, subStart, subCount, subResult);
return 0;
}
// Function to get text input
void read_Line (char buffer[])
{
char character;
int i = 0;
do
{
character = getchar();
buffer[i] = character;
++i;
}
while (character != '\n');
buffer[i - 1] = '\0';
}
// Function to count determine the length of a string
int string_Length (char string[])
{
int len = 0;
while (string[len] != '\0')
{
++len;
}
return len;
}
// Function to extract substring
void sub_String (char source[], int start, int count, char result[])
{
int i, j, k;
k = start + count;
for (i = start, j = 0; i < k || i == '\0'; ++i, ++j)
{
result[j] = source[i];
}
result[k] = '\0';
printf("%s\n", result);
}
I am using Code::Blocks on Linux Mint.
Being someone that just started learning programming recently with CS50 and 'Programming in C' books, I did not know how to setup the debugger in Code::Blocks. But thanks to the push by #paulsm4, I managed to get the debugger working. Using the watches window of the debugger, I could see that the while loop in the main function was overwriting the first character in the source array with a null character. The fix was to add a break statement. Thanks to #WhozCraig and #Pascal Getreuer for pointing out other errors that I had missed. This is the corrected code now:
/* Programme to extract a portion from a string using function
sub-string (source, start, count, result) ex9.4.c
ALGORITHM
Get text input into a char array (declare to be fixed size);
Determine length of source string;
Prepare result array to be dynamic length using desired count + 1;
Copy from source array into result array
*/
#include <stdio.h>
#include <stdbool.h>
#define MAX 501
void read_Line (char buffer[]);
int string_Length (char string[]);
void sub_String (char source[], int start, int count, char result[]);
int main(void)
{
char strSource[MAX];
bool end_Of_Text = false;
int strCount = 0;
printf("This is a programme to extract a sub-string from a source string.\n");
printf("\nType in your text (up to 500 characters).\n");
printf("When you are done, press 'RETURN or ENTER'.\n\n");
while (! end_Of_Text)
{
read_Line(strSource);
if (strSource[0] == '\0')
{
end_Of_Text = true;
}
else
{
strCount += string_Length(strSource);
}
break;
}
// Declare variables to store sub-string parameters
int subStart, subCount;
char subResult[MAX];
printf("Enter start position for sub-string: ");
scanf(" %i", &subStart);
getchar();
printf("Enter number of characters to extract: ");
scanf(" %i", &subCount);
getchar();
// Call sub-string function
sub_String(strSource, subStart, subCount, subResult);
return 0;
}
// Function to get text input
void read_Line (char buffer[])
{
char character;
int i = 0;
do
{
character = getchar();
buffer[i] = character;
++i;
}
while (character != '\n');
buffer[i - 1] = '\0';
}
// Function to count determine the length of a string
int string_Length (char string[])
{
int len = 0;
while (string[len] != '\0')
{
++len;
}
return len;
}
// Function to extract substring
void sub_String (char source[], int start, int count, char result[])
{
int i, j, k;
k = start + count;
// Source[i] == '\0' is used in case count exceeds source string length
for (i = start, j = 0; i < k || source[i] == '\0'; ++i, ++j)
{
result[j] = source[i];
}
result[j] = '\0';
printf("%s\n", result);
}

Reversing a two dimensional character array in C

i am trying to write a program which reverses a entire string and also may print reversing each word of the string more than one time.
For example my string is:
"2
Fox jumps over the lazy dog."
for this, the output should be:
.god .god yzal yzal eht eht revo revo spmuj spmuj xoF xoF.
I am trying to store each word in a 2d array and then reverse each word but i am not able to do that.
here is my code. kindly help
Note: how do we provide EOF in console
#include <stdio.h>
#include <stdlib.h>
int main() {
char string[100][100];
char ch;
int i = 0, j = 0, l = 0, count = 0, x = 0, y = 0;
while ((ch = getchar()) != EOF) {
string[i][l++] = ch;
if (ch == ' ') {
string[i][l] = '\n';
i++;
l = 0;
count++;
}
}
for (x = 0; x <= count; x++) {
int length = strlen(string[x]) - 1;
for (y = length; y >= 0; --y)
printf("%s", string[y]);
}
return 0;
}
Here are a few changes to your code check the comments for explanation.
int main()
{
char string[100][100];
char ch;
int i=0,j=0, l=0, count=0, x=0, y=0;
while((ch=getchar())!=EOF)
{
string[i][l++] = ch;
if(ch==' ')
{
string[i][l] = '\0'; //make the string null terminated otherwise you cant work with its length
i++;
l=0;
count++;
}
}
string[i][l]='\0'; //make the last string null terminated
for(x=count; x>=0; x--) //read from last counter
{
int length = strlen(string[x])-1;
for(y=length; y>=0; --y)
{
printf("%c", string[x][y]); //print by each character and not string.
}
}
return 0;
}
Corrections in your code:
C strings are null terminated, but you are terminating your strings with newline \n character, which is wrong.
You are storing the whitespace with the string, reversing will be difficult in this case.
Your print statement won't reverse the string, print it character by character.
For the output that you need, you can consider this code.
#include <stdio.h>
#include <stdlib.h>
int main() {
char string[100][100];
char ch;
int i = 0, j = 0, l = 0, count = 0, x = 0, y = 0;
while ((ch = getchar()) != EOF) {
if (ch == ' ') {
string[i][l] = '\0'; /// Null terminate the string
i++;
l = 0;
count++;
}
else
string[i][l++] = ch; /// Don't add whitespace to the string
}
string[i][l] = '\0';
for (x = count; x >= 0; x--) {
int length = strlen(string[x]) - 1;
for (y = length; y >= 0; --y)
printf("%c", string[x][y]); /// Print the string in reverse
printf(" ");
for (y = length; y >= 0; --y)
printf("%c", string[x][y]); /// Twice
printf(" ");
}
return 0;
}
Input
2 Fox jumps over the lazy dog.
Output
.god .god yzal yzal eht eht revo revo spmuj spmuj xoF xoF 2 2
See http://ideone.com/qaIoW9
If I understand you want to duplicate each reversed word N times as specified by the first number in the string, then something like the following would work:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *strrevdup (char* str);
int main (int argc, char **argv) {
if (argc < 2 ) {
fprintf (stderr, "error: insufficient input, usage: %s \"# string\"\n",
argv[0]);
return 1;
}
char *str = strdup (argv[1]);
char *p = str;
char *rev = NULL;
int mult = 0;
int i = 0;
while (*p && *p != ' ') p++;
*p = 0;
mult = atoi (str);
*p = ' ';
if (!mult) return 1;
while (*p && *p == ' ') p++;
rev = strrevdup (p);
char *r = rev;
printf ("\n the reversed string with duplicated words '%d' times is:\n\n", mult);
for (p = strtok (r, " "); p; p = strtok (NULL, " \n"))
for (i = 0; i < mult; i++)
printf (" %s", p);
printf ("\n\n");
free (str);
free (rev);
return 0;
}
/** strrevdup - reverse duplicate string, swaps src & dest each iteration.
* Takes valid string, duplicates and reverses, original is preserved.
* Returns pointer to reversed string on success, NULL otherwise.
* Requires string.h, caller is responsible for freeing memory allocated.
*/
char *strrevdup (char* str)
{
if (!str) {
printf ("%s() error: invalid string\n", __func__);
return NULL;
}
char *rstr = strdup (str);
char *begin = rstr;
char *end = rstr + strlen (rstr) - 1;
char tmp;
while (end > begin){
tmp=*end;
*end-- = *begin;
*begin++ = tmp;
}
return rstr;
}
Output
$ ./bin/strrevndup "2 Fox jumps over the lazy dog."
the reversed string with duplicated words '2' times is:
.god .god yzal yzal eht eht revo revo spmuj spmuj xoF xoF
you may try this code although it will reverse and print words in different lines.. you may try few more things to get the desired answer.
` #include <stdio.h>
#include <stdlib.h>
#include<string.h>
int main()
{
char string[1024][1024];
char ch;
int t,z;
scanf("%d",&t);
z=t;
int i=0, l=0, count=0, x=0, y=0;
getchar();
while((ch=getchar())!=EOF)
{
if(ch=='\n')
{
i++;
l=0;
count++;
string[i][l++] = ch;
i++;
l=0;
}
else if(ch==' ')
{
i++;
l=0;
count++;
}
else{
string[i][l++] = ch;
}
}
for(x=count+1; x>=0; x--)
{
if(string[x][0]=='\n')
{
printf("\n");
}
else{
char *rev=strrev(string[x]);
while(t--)
printf("%s ",rev);
t=z;
}
}
return 0;
}`

Pattern matching in long text string

I wrote this code and it works in some cases. Sometimes, however, it fails, and I just can't see why. Can someone please help me spot the error?
It works for:
String: ishanthakkar ishan
patter: ishan
But it fails for:
String: cpr ograming
patter: cpr
Source:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int *compute_prefix_function(char *pattern, int psize)
{
int k = -1;
int i = 1;
int *pi = malloc(sizeof(int)*psize);
if (!pi)
return NULL;
pi[0] = k;
for (i = 1; i < psize; i++) {
while (k > -1 && pattern[k+1] != pattern[i])
k = pi[k];
if (pattern[i] == pattern[k+1])
k++;
pi[i] = k;
}
return pi;
}
// This function find matching string in O(n) time, so iterate through text string only once, when unmatching character found; it proceed with next character and start comparing with first character of string to be searched i.e pattern
int kmp(char *target, int tsize, char *pattern, int psize)
{
int i;
int *pi = compute_prefix_function(pattern, psize);
int k = -1;
if (!pi)
return -1;
for (i = 0; i < tsize; i++) {
while (k > -1 && pattern[k+1] != target[i])
k = pi[k];
if (target[i] == pattern[k+1])
k++;
if (k == psize - 1) {
free(pi);
return i-k;
}
}
free(pi);
return -1;
}
int main(int argc, const char *argv[])
{
char target[200];
char *ch = target;
char pattern[20];
int i;
printf("Enter the string: \n");
fgets(target,100,stdin);
printf("Enter the string to be matched: \n");
fgets(pattern,20,stdin);
i = kmp(target, strlen(target), pattern, strlen(pattern));
if (i >= 0)
printf("matched #: %s\n", ch + i);
getch();
return 0;
}
The fgets function reads and includes the ending CR (or CRLF) in the string.
Add a chomp() function, like
void chomp(char *s) {
int n = strlen(s);
while (n && (s[n-1]==10 || s[n-1]==13)) s[--n] = 0;
}
that removes any CR or LF at the end of the string.
Then chomp() pattern and target before calling kmp() (and after the scanf())
chomp(target);
chomp(pattern);
i = kmp(target, strlen(target), pattern, strlen(pattern));
the program should behave better.
Note: 10 is '\n' (LF) and 13 is '\r' (CR)
Got clue:
i = kmp(target, strlen(target), pattern, strlen(pattern));
was passing string length+1(for null character) so it was giving false result for some text string
i = kmp(target, strlen(target)-1, pattern, strlen(pattern)-1);
works for all cases!
Thanks to all of you for your time!

Resources