我目前正在研究的是从输入的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()
而不是它找到的第一个点?
答案 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 字符串部分并将部分复制到您的存储空间为.mp3
和artist
。
在快速示例中将各个部分放在一起,您可以执行以下操作:
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
等,但对于基本逻辑,您不能简单地使用给出的信息,涉及的长度和指针。如果您有任何问题,请告诉我。