如何只解析字符串的最后一个字符?

时间:2016-01-19 20:33:25

标签: c++ c string parsing strtok

我目前正在研究的是从输入的mp3字符串中解析歌曲标题和艺术家。

字符串的格式为" artist-title.mp3",我们的老师向我们提供了这些信息,并确保任何一个歌名中都没有-个字符,但标题中可能有.个字符。

我现在编写的方式与strtok()函数完美匹配,只抓取这些字符之前的内容并将它们放入标题/艺术家字段中。

像这样:

//Parse out the artist and title from the song
    char* artistName = strtok(song, "-");
    char* songName = strtok(NULL, ".");

    //Allocate a new block of memory to the blocks songInfo fields with the correct size
    newBlock->songInfo.artist = (char*)malloc(sizeof(char) * strlen(artistName) + kNullTerminator);
    newBlock->songInfo.title = (char*)malloc(sizeof(char) * strlen(songName) + kNullTerminator);

唯一的问题是如果标题名称中有一个点,它将不会将完整的字符串识别为标题,它会将其剪掉。我想知道的是我如何使用.获取最后strtok()而不是它找到的第一个点?

2 个答案:

答案 0 :(得分:3)

首先,您可以使用strrchr()找出输入中.的最后一次出现。

也就是说,使用strtok(),您也可以完成此操作。继续解析相同的字符串,直到你得到NULL然后,考虑最后但只有一次的情况。

答案 1 :(得分:0)

使用strtok实际上可能会使事情变得比他们需要的更难。如果您的老师告诉您字符串格式为artist-title.mp3并且保证字符串中只有一个'-'(即分隔符),那么您已经拥有了所需的所有信息在没有strtok的情况下将字符串解析为艺术家标题

想一想。您需要做的就是阅读每一行。您首先要确认该行以.mp3结尾,并且该行至少为8个字符长(如果使用面向行的输入函数读取,请{{1 }或fgets)。为什么呢?

getline

如果该行少于 a - a . m p 3 \n +-+-+-+-+-+-+-+- 1 2 3 4 5 6 7 8 个字符,则您无法拥有艺术家,分隔符,标题 .mp3 (带尾随换行符)。只需拨打8即可获得长度。您可以通过从strlen开始的.mp3简单调用来确认字符串的最后4个字符为strncmp

接下来,您要确认该行包含line[len-5]分隔符。对'-'的简单调用都会确认存在并返回指向行内分隔符位置的指针。

知道行的长度和strchr分隔符的位置,您的行已经被解析。您需要做的就是在'-'分隔符和'-'(在'.'中) nul-terminate 字符串部分并将部分复制到您的存储空间为.mp3artist

在快速示例中将各个部分放在一起,您可以执行以下操作:

title

Sammple输入文件

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

typedef struct {
    char *artist;
    char *title;
} track;

enum { MAXS = 128, MAXC = 256 };

int main (int argc, char **argv) {

    track album[MAXS] = {{NULL}, {NULL}};
    char line[MAXC] = {0};
    size_t i, idx = 0;
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {
        fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
        return 1;
    }

    while (fgets (line, MAXC, fp)) 
    {
        char *p = strchr (line, '-');       /* pointer to '-'    */
        size_t len = strlen (line);         /* length of line    */

        if (!p || len < 8 || strncmp (&line[len-5], ".mp3", 4))
            continue;                       /* skip invalid line */

        *p = 0;                             /* nul-terminate at '-' */
        line[len-5] = 0;                    /* nul-terminate at '.' */

        album[idx].artist = strdup (line);  /* alloc/copy artist */
        album[idx++].title = strdup (p + 1);/* alloc/copy title  */

        if (idx == MAXS) {  /* check index against max songs */
            fprintf (stderr, "warning: MAXS songs reached.\n");
            break;
        }
    }

    printf ("\nArtists & Titles\n");
    for (i = 0; i < idx; i++)
        printf ("\n artist : %s\n title  : %s\n",
                album[i].artist, album[i].title);

    for (i = 0; i < idx; i++) {
        free (album[i].artist);
        free (album[i].title);
    }

    return 0;
}

<强>输出

$ cat dat/artist-title.txt
This is a collection of songs artist-title in mp3 format

# favorite artists
SO Superband-Against the String.mp3
# a capella
.30 Caliber Quartet-Songs to Die For.mp3
# duets
Dot.com.duet-Internet Harmony.mp3

您可以添加其他验证以防止短读取,或检查大写$ ./bin/fgets_artist_title dat/artist-title.txt Artists & Titles artist : SO Superband title : Against the String artist : .30 Caliber Quartet title : Songs to Die For artist : Dot.com.duet title : Internet Harmony 等,但对于基本逻辑,您不能简单地使用给出的信息,涉及的长度和指针。如果您有任何问题,请告诉我。