Trying to copy the remainder of a string after a character

I am trying to copy the remainder of a user inputted string. It is always input in the following: airport, 00:00, 00:00. The numbers are flight times and layover times. In my code I've gotten it to spit out the airport, but trying to use strchr to find everything after the 1st "," is a pain. Is there a way I can remove the airport and put the rest into a new string and continue to use strchr? I have to reformat the strings separated by commas is the goal. The end result should be "city has flight time tt.tt hoursand layover time tt.tt hours". I cannot use scanf or the like so it looks like strchr and strcopy might be my only options. Any help is appreciated.

What I have currently gives me an error when trying to find the char after the last "," in the string.

Assignment Rules: Do not use strtok(), any scanf-related functions, any functions that do tokenization of string data.

int main()
{
    int counter = 0;
    int flightTimeNum = 0;
    char userInput[81] ="";
    char userInputNew[81] = "";
    char cityNew[20] = "";
    char flightTime[20] = "";
    char layOverTime[20] = "";


    fgets(userInput, 81, stdin);
    char *city;
    char *flight;
    char *layover;

    city = strchr(userInput, ',');
    strncpy(cityNew, userInput, city - userInput);
    printf("%s\n" ,cityNew);

    layover = strrchr(userInput, ',');
    strncpy(layOverTime, userInput, layover - userInput);
    printf("%s\n", layOverTime);

    printf("Press ENTER key to Continue\n");
    getchar();

}

If you want to use strchr you could consider creating substrings by replacing each ',' with a null terminator \0 and then setup the pointers to each sub string based on the length of the previous string.

Alternatively, you could can through the string accumulating the characters until you reach a , and then terminate the buffer and start accumulating the next part of the string into the next buffer, and repeat until you reach the null terminator of the userInput.

Example of the first approach, note you should validate that you were able to create the expected number of substrings etc. just in case the user enters invalid data.

// NULL terminate each substring
char *p = userInput;    // Point to the beginning of the string
for(;;) {
    p = strchr(p, ','); // Find first ',' starting from 'p'
    if (!p) break;      // If not found break out of loop
    *p = '\0';          // otherwise replace ',' with a null terminator
    ++p;                // move pointer 'p' to the next character
}

// Setup pointers to each substring
city = userInput; 
flight = city + strlen(city) + 1;
layover = flight + strlen(flight) + 1;

Erlang -- string, Removes anything before SearchPattern in String and returns the remainder of the Remaining characters in the string after the integer are returned in Rest. Try this string str = " this is a #string"; string ext = str.Substring(0, str.LastIndexOf(" #") + 1); THis should work. tweak it as pr your needs.

While you are free to parse the information from each line with a pointer and strchr (or by simply walking a pointer down your buffer), when dealing with formatted input, using a formatted input function like sscanf can greatly help.

Let's take a look at both. In your question you want to read with fgets (good), and then find the first comma, and then copy the remainder of the line to a new buffer. All good so far. The only caveat is once you locate the first comma, you still must advance the pointer from the comma, skipping any whitespace, until you reach the first character for the remainder of the times (rest of the line).

A simple approach that simply outputs the remainder of the string following the first comma omitting any intervening whitespace could be:

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define MAXC 1024   /* if you need a constant, define one (or more) */

int main (void) {

    char buf[MAXC];

    while (fgets (buf, MAXC, stdin)) {      /* read with fgets */
        char *p;
        buf[strcspn (buf, "\r\n")] = 0;     /* trim '\n' from end */
        if ((p = strchr (buf, ','))) {      /* find 1st ',' */
            do
                p++;                    /* advance pointer */
            while (*p && isspace (*p)); /* to end or 1st non-whitespace */
        }
        printf ("rest of string: '%s'\n", p);   /* output rest of line */
    }
}

(note: when declaring constants, don't Skimp on buffer size.)

Example Input File

$ cat dat/airport_times.txt
KOCH, 01:01, 01:51
KAXX, 03:50, 05:40
KADS, 07:40, 09:30

Example Use/Output

$ ./bin/airport_gettimes <dat/airport_times.txt
rest of string: '01:01, 01:51'
rest of string: '03:50, 05:40'
rest of string: '07:40, 09:30'

Now let's look at using fgets for the read and the formatted-input function sscanf to parse all needed values from each line. (or you could use fscanf to do it in one call, but you are better off using fgets and then sscanf to (1) ensure you consume an entire line of data and (2) can independently validate the read and parse of values.

The approach is similar, read with fgets, but then instead of looking for the first comma with strchr, simply use sscanf to read the ICAO, Arrival time and Departure Time into separate buffers in one call. ALWAYS validate the RETURN of any of the scanf functions to ensure the expected number of conversions took place.

Thinking ahead, let's not just use three separate and unrelated buffers. Instead let's declare a struct to hold all three, the icao, ariv & dept buffers. That way if reading multiple entries into memory, you can simply declare an array of struct and read/parse all values for later user. (the array is left to you)

A simple example here could be:

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define MAXC 1024   /* if you need a constant, define one (or more) */
#define ICAO    6   /* will work for ICAO and time buffer lengths */

typedef struct {
    char icao[ICAO],
        ariv[ICAO],
        dept[ICAO];
} flight_t;

int main (void) {

    char buf[MAXC];

    while (fgets (buf, MAXC, stdin)) {      /* read with fgets */
        flight_t flt = { .icao = "" };      /* declare struct */
        /* separate all value in line into struct, validating return */
        if (sscanf (buf, "%5[^,], %5[^,], %5[^,]", 
                    flt.icao, flt.ariv, flt.dept) == 3)
            /* if sscanf succeeds, output (or use) the values */
            printf ("%s  %s (arrival)  %s (departure)\n",
                    flt.icao, flt.ariv, flt.dept);
    }
}

(note: how the field-width modifier is used before each character class conversion specifier to protect the array bounds for each buffer with "%5[^,], %5[^,], %5[^,]". If you have questions about the format-string, just ask.)

Same input file.

Example Use/Output

$ ./bin/airport_parsetimes <dat/airport_times.txt
KOCH  01:01 (arrival)  01:51 (departure)
KAXX  03:50 (arrival)  05:40 (departure)
KADS  07:40 (arrival)  09:30 (departure)

The benefit here, is you now have all values coordinated as a single object, but stored independently so you can access any of the icao, ariv or dept values as needed while, in the case of an array of struct, still being able to sort the array on any of the struct members while maintaining the association of icao, arrival and departure times.

There are many, many more ways to put the pieces of the puzzle together. The next step would be to dynamically allocate your array of struct and realloc as needed to allow you to read an unknown and unlimited number of records (up to the physical memory of your computer). However, the two approaches, (1) parse the buffer with a pointer, or (2) use a formatted input function cover a majority of the cases. All that is left is building upon that foundation as desired.

Extract substrings after specified positions, This MATLAB function extracts the substring that begins after startStr and ends with the last character of str. I am trying to come up with a formula that would return the start of a text string until it hits the space and then another that would return the remainder after hitting the last space. Text to columns doesn't work too well since it is a different number of names for different people.

strchr() will return a pointer to the character, meaning it will move forward in the string. You can use it as a new string for further operations:

char str[] = "airport, 00:00, 00:00.";
char* rem = strchr(str, ','); // rem is now ", 00:00, 00:00."
rem += 2; // rem is now "00:00, 00:00."
rem = strchr(rem, ','); // rem is now ", 00:00, 00:00."
rem += 2; // rem is now "00:00."
*strchr(rem, '.') = 0; // rem is now "00:00" (dot removed)

Of course, you should check for NULL return, when the character does not exist...

EDIT: Too tempting to give my own implementation for you to see how pointers work in C:

char str[] = "airport, 00:00, 00:00.";
char* city = str; // "airport, 00:00, 00:00."
char* departure = strchr(str, ','); // ", 00:00, 00:00."
char* arrival = strchr(departure+1, ','); // ", 00:00."
// Clean up
*departure = 0; // city is now "airport"
departure += 2; // depature is now "00:00, 00:00."
*arrival = 0; // departure is now "00:00"
arrival += 2; // arrival is now "00:00."
*strchr(arrival, '.') = 0;  // arrival is now "00:00"

Again, if it's user input, you must check for strchr() returning NULL, because it will happen.

Substring in C#, C# Substring is a contiguous sequence of characters within a string. In other words, a Now, if you want to retrieve a substring everything after 12th position. You can simply pass the starting position in the string to get the rest of the string as a substring. 65+ Blazor Native Components – Try them free. $\begingroup$ Is it after a specific character, or after a specific index? $\endgroup remove single characters from string. 3. copy and paste this URL into

Here is an alternate solution using a function to look for the first digit.

This will work better than strstr() if you only know that the string you care about starts with a digit.

#include <stdio.h>
#include <string.h>

char* find_digit(char* string)
{
  while(*string != '\0') {
    char ch = *string;

    if(*string >='0' && *string <= '9') {
      return string;
    }
    string++;

  }
}
int main()
{
  char str[] = "airport, 00:00, 00:00.";

  char* ret = find_digit(str);

  char* remainder = ret + strlen(needle);

  printf("Remainder is: %s\n",remainder);

  return 0;
}

String Functions (The GNU Awk User's Guide), For these functions, the first character of a string is at position (index) one. values (see section Arrays of Arrays), they will come last, after all scalar values. gawk 'BEGIN { print length(x) ; x[1] = 1 }' -| 0 error→ gawk: fatal: attempt to use scalar the number of characters remaining in the string, counting from character start . for substr, a character vector as long as x containing the specified portions of each character string. Any shorter vector of start and stop is replicated. for substring , a character vector as long as the longest of text , first and last , containing the specified portions of each character string.

[PDF] 059-30: A Clever Demonstration of the SAS , starting position can be determined by counting the string characters from left to right. length operates on the remainder of the string. may or may not be a space after the comma, so the TRIM & LEFT functions are invoked to remove all� Zero or more of the preceding character. a* matches the empty string, a, aa, etc, but not b. + One or more of the preceding character. a+ matches a, aa, etc, but not the empty string or b.. Matches any character [ax1] Any of a,x,1: a-d: matches any of a,b,c,d \w: The \w meta character is used to find a word character. A word character is a

How to remove texts before or after a specific character from cells in , Delete texts before or after specific character by Find and Replace in Excel Select a blank cell, copy and paste the below formula into it, and press Enter key. to remove everything before or after this comma from cells, please try the Split Cells No longer need memorizing formulas and VBA codes, give your brain a rest� String that indicates the start of the substring to extract, specified as a string array, a character vector, or a cell array of character vectors. extractAfter excludes startStr from the substring to extract.

JavaScript String substring() Method, blur canplay canplaythrough change click contextmenu copy cut dblclick drag dragend dragenter More "Try it Yourself" examples below. Definition and Usage. The substring() method extracts the characters from a string, between two specified indices, Begin the extraction at position 2, and extract the rest of the string:. Remainder of the text, returned as a string array, a character vector, or a cell array of character vectors. If strtok finds a delimiter in str , then remain includes all text starting at, and including, that delimiter and ending at the end of the text.

Comments
  • Have you looked at strtok?
  • Sorry ill update my post, the rules are "Do not use strtok(), any scanf-related functions, any functions that do tokenization of string data"
  • I've been basically pulling my hair out trying to figure out how to do it when strchr seems to only like for one instance of a specific character, so any help might just save my sanity!
  • Since this is an assignment I'm not going to post an answer, but here is a hint. strncpy(flightTime, userInput, flightTime - userInputNew); --> This doesn't look right at all. flightTime and userInputNew do not point to the same array. That subtraction will not give you what you want. You probably want to base your arithmetic off city and flight. But you should also check your assumptions that city > flight and that neither are NULL.
  • you also want to make sure you null terminate your strings
  • Replacing characters by nuls is what I usually do (and what strtok() does internally), as it allows you to use strlen() and others. But note that it will fail on const char*, when the memory is really read-only (e.g. stored in ROM).
  • @Matthieu, good point however the example does show this coming in as user input so that would not apply in this particular case.
  • Yes, it usually isn't a problem (even const char* can be cast to char*...). I just wanted to raise that point because it happened to me in my sxmlc parser: people use it in embedded OS where such things happen (configuration file stored in PROM) and writing to it causes a core dump...
  • *p++ = 0; sorry ;)
  • @Matthieu, no need to be sorry help is always appreciated (at least it should be). Since the OP is clearly learning, right or wrong, I chose to separate each step so that I could comment it and hopefully make it clear what was going on.
  • Using strchr() is easier in that case. The airport name is probably unknown.