Thread: Tokenizing end of string to next line

  1. #1
    Registered User
    Join Date
    Nov 2017
    Posts
    29

    Tokenizing end of string to next line

    I'm having trouble getting a string tokenizing function to scan the last value of a string and proceed to the next line. This runs in a for loop to tokenize multiple lines.

    Example: PART,2.00,1,.050,F

    I have tried a few combinations such as

    Code:
    temp = strtok(NULL, "\n");
    and

    Code:
    temp = strtok(NULL, "");
    I put a watch on it and the initial token is stored to the array but bugs out then stores the token from the next in that same index. I'm running a test print of my arrays and this one should print

    "F
    V
    V"

    but prints

    "V

    V".

    What is the best solution?

  2. #2
    Registered User
    Join Date
    Dec 2017
    Posts
    1,633
    Just use sscanf.
    Code:
    #include <stdio.h>
    
    int main() {
        char s[] = "PART,2.00,1,.050,F\n";
        char name[100], grade;    
        double price, radius;
        int quantity;
    
        sscanf(s, "%[^,],%lf,%d,%lf,%c", name, &price, &quantity, &radius, &grade);
    
        printf("%s\n%f\n%d\n%f\n%c\n", name, price, quantity, radius, grade);
    
        return 0;
    }
    A little inaccuracy saves tons of explanation. - H.H. Munro

  3. #3
    Registered User
    Join Date
    Nov 2017
    Posts
    29
    [QUOTE=john.c;1277984]Just use sscanf.
    QUOTE]

    I forgot to mention this is reading from a .txt file. I'll post the loop.

    Code:
        for (N=0; fscanf(fpin, "%s ",descriptor) != EOF; N++){
                printf("%s\n", descriptor);
            for(i=0; i < N; i++);{
                temp = strtok(descriptor, ",");
                result_p = strcmp(temp, part);
                if (result_p == 0){
                   temp = strtok(NULL, ",");    // Temporary variable for string tokenizing
                   p_dim[i] = atof(temp);       // Part dimension, converted from string to double
                   temp = strtok(NULL, ",");
                   t_sens[i] = atoi(temp);      // Sensitivity, converted from string to int
                   temp = strtok(NULL, ",");
                   tol[i] = atof(temp);         // Tolerance, converted from string to double
                   temp = strtok(NULL, "\n");
                   t_status[i] = temp;          // Tolerance status, either V or F
                }
                else if (result_p != 0){
                    temp = strtok(NULL, ",");    // Temporary variable for string tokenizing
                    key_min = atof(temp);        // Lower key characteristic, converted from string to double
                    temp = strtok(NULL, " ");
                    key_max = atof(temp);        // Upper key characteristic, converted from string to double
                }
            }
        }

  4. #4
    Registered User
    Join Date
    Dec 2017
    Posts
    1,633
    You have an extraneous semicolon at the end of the second for. Watch out for those! It means that loop is doing nothing.

    It's also an error to end a scanf format with whitespace. Get rid of the space after the %s. Also note that %s will stop if it encounters a space. It's certainly not the normal way to read an entire line. fgets is for that.

    Your loop looks very strange. I can't understand why you would want the inner loop to loop zero times the first iteration of the outer loop, once the next iteration, twice the next, etc. Is that really what you want?

    It would be better for you to describe the data, not show code. I'm pretty certain an sscanf would do it so you don't have to "tokenize" anything.
    A little inaccuracy saves tons of explanation. - H.H. Munro

  5. #5
    Registered User
    Join Date
    Nov 2017
    Posts
    29
    It would be better for you to describe the data, not show code. I'm pretty certain an sscanf would do it so you don't have to "tokenize" anything.
    The data given is as follows:

    PART,3.00,+1,0.010,F
    PART,0.975,-1,0.025,V
    PART,2.00,-1,0.050,V
    GAP,0.000,0.080

    The starting word and last letter are identifiers, and the numbers get math done to them in several stages through functions.

    Get rid of the space after the %s.

    You have an extraneous semicolon at the end of the second for.
    Up to this point all the arrays are indexing properly with the exception of t_status[]. Making these changes gave me really weird results so I reverted back for now.

    I see how this could potentially be simplified with your sscanf example and would like to learn more.

  6. #6
    Registered User
    Join Date
    Dec 2017
    Posts
    1,633
    Try something like this:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main() {
        char line[1000], name[100], status;
        double dim, tol, keymin, keymax;
        int sens;
        FILE *fpin = fopen("parts.txt", "r");
    
        while (fgets(line, sizeof line, fpin) != NULL) {
            if (strncmp(line, "PART,", 5) == 0) {
                sscanf(line, "%[^,],%lf,%d,%lf,%c",
                       name, &dim, &sens, &tol, &status);
                printf("%s;%f;%d;%f;%c\n", name, dim, sens, tol, status);
            }
            else {
                sscanf(line, "%[^,],%lf,%lf", name, &keymin, &keymax);
                printf("%s;%f;%f\n", name, keymin, keymax);
            }
        }
    
        fclose(fpin);
        return 0;
    }
    A little inaccuracy saves tons of explanation. - H.H. Munro

  7. #7
    Registered User
    Join Date
    Nov 2017
    Posts
    29
    [QUOTE=john.c;1277991]Try something like this:
    QUOTE]

    This is great! Would getting these values into an array be as simple as changing the declarations and putting this system into a for loop?

  8. #8
    Registered User
    Join Date
    Dec 2017
    Posts
    1,633
    Quote Originally Posted by scotdani View Post
    This is great! Would getting these values into an array be as simple as changing the declarations and putting this system into a for loop?
    You don't need a for loop, just an index variable, something like this:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main() {
        char line[1000], status[100];
        double dim[100], tol[100], keymin, keymax;
        int sens[100];
        FILE *fpin = fopen("parts.txt", "r");
    
        int n = 0;
        while (fgets(line, sizeof line, fpin) != NULL) {
            if (strncmp(line, "PART,", 5) == 0) {
                sscanf(line, "%*[^,],%lf,%d,%lf,%c",
                       &dim[n], &sens[n], &tol[n], &status[n]);
                n++;
            }
            else
                sscanf(line, "%*[^,],%lf,%lf", &keymin, &keymax);
        }
    
        fclose(fpin);
    
        for (int i = 0; i < n; i++)
            printf("%f;%d;%f;%c\n", dim[i], sens[i], tol[i], status[i]);
        printf("%f;%f\n", keymin, keymax);
    
        return 0;
    }
    I'm not sure what you want to do with the keymin, keymax values. I'm assuming there's only one line like that.
    A little inaccuracy saves tons of explanation. - H.H. Munro

  9. #9
    Registered User
    Join Date
    Nov 2017
    Posts
    29
    Quote Originally Posted by john.c View Post
    You don't need a for loop, just an index variable.

    I'm not sure what you want to do with the keymin, keymax values. I'm assuming there's only one line like that.
    Thanks for the help. This is working great, and yes your assumption is correct. Now to brush up on passing arrays to functions.

    As I mentioned above, the numbers get math done to them.

    A function that processes the numbers is giving me unusually large values.

    Code:
    double basic_dim (double p_dim[], double t_sens[], double tol[], double* basic_gap, double* basic_gap_tol, double* upper_gap, double* lower_gap, double key_max, double key_min){
            int j=0;
            int k;
                for(j=0; j<k; j++){
            *basic_gap += (p_dim[j] * t_sens[j]);
            *basic_gap_tol += tol[j];
            }
            *upper_gap = *basic_gap + *basic_gap_tol;
            *lower_gap = *basic_gap - *basic_gap_tol;
    
            printf("\nBasic gap: %.3lf\n", basic_gap);
            printf("Basic gap tolerance: %.3lf\n", basic_gap_tol);
            printf("Upper gap: %.3lf\n", upper_gap);
            printf("Lower gap: %.3lf\n", lower_gap);
        return;
        }
    Basic_gap is the value in p_dim times the t_sens number, then added all together.

    Basic_gap_tol is the values of tol[n] added together.

    Upper and lower gap is simply basic_gap +/- basic_gap_tol

    I've never been very good with passing between functions.

  10. #10
    Registered User
    Join Date
    Dec 2017
    Posts
    1,633
    You are looping j from 0 to k ... but what in the world is k? At the moment you're using it uninitialized (your compiler should warn you about that).

    BTW, you can gather some of the data together into structs:
    Code:
    typedef struct Xxxxx {         // give this an appropriate name
        double p_dim;
        double t_sens;
        double tol;
    } Xxxxx;                             // same name here
    
    typedef struct Gap {
        double basic;
        double basic_tol;
        double upper;
        double lower;
    } Gap;
    
    typedef struct Key {
        double min;
        double max;
    } Key;
    
    // Rename the xxxxx stuff
    double basic_dim(Xxxxx *xxx, Gap *gap, Key *key) {
        int limit = SET THIS TO SOMETHING!!!!!;
        for (int i = 0; i < limit; i++) {
            gap->basic += xxx[i].p_dim + xxx[i].t_sens;
            gap->basic_tol += xxx[i].tol;
        }
        gap->upper = gap->basic + gap->basic_tol;
        gap->lower = gap->basic - gap->basic_tol;
    }
    If you don't use key in the function then you don't need to pass it in.
    Last edited by john.c; 04-09-2018 at 09:55 AM.
    A little inaccuracy saves tons of explanation. - H.H. Munro

  11. #11
    Registered User
    Join Date
    Nov 2017
    Posts
    29
    Quote Originally Posted by john.c View Post
    You are looping j from 0 to k ... but what in the world is k? At the moment you're using it uninitialized (your compiler should warn you about that).

    BTW, you can gather some of the data together into structs:
    I've only had a small introduction to structs but I'll try this out.

    Changing that k variable to sizeof fixed the issue I was having before. So many ins and outs I need to remember!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Tokenizing string
    By Ducky in forum C++ Programming
    Replies: 4
    Last Post: 12-31-2017, 10:00 AM
  2. Tokenizing a string
    By sigur47 in forum C Programming
    Replies: 3
    Last Post: 05-07-2012, 07:16 PM
  3. Tokenizing a string
    By BdON003 in forum C++ Programming
    Replies: 2
    Last Post: 11-23-2009, 10:45 PM
  4. Tokenizing Command Line Arguments
    By NickNore in forum C Programming
    Replies: 3
    Last Post: 09-24-2007, 12:18 AM
  5. Tokenizing a C++ string
    By Lurker in forum C++ Programming
    Replies: 3
    Last Post: 04-07-2004, 06:31 AM

Tags for this Thread