【问题标题】:Splitting data from a file into arrays - C将文件中的数据拆分为数组 - C
【发布时间】:2021-06-11 07:41:32
【问题描述】:

我有一个名为 song.txt 的 .txt 文件,我正在尝试设计一种方法来打开并读取该文件的内容,然后按艺术家姓名和歌曲名称对输入进行排序,然后按以下格式打印出来:

File contents:                                              Desired output format:

Bon Iver                                                    Arcade Fire
29 #Strafford APTS***4:05                                   o Cold Wind***3:12
00000 Million***3:53                                        o Rebellion (Lies)***5:10
re: Stacks***6:40                                           o Neighborhood #1 (Tunnels)***4:48
                                                            o Neighborhood #3 (Power Out)***5:12
Future Islands                                              o Wake Up***5:39
Tin Man***3:14                                            
Seasons (Waiting on You)***3:46                             Bon Iver
Grease***4:35                                               o 00000 Million***3:53
Spirit***4:22                                               o 29 #Strafford APTS***4:05
                                                            o re: Stacks***6:40
Arcade Fire                                               
Rebellion (Lies)***5:10                                     Future Islands
Wake Up***5:39                                              o Grease***4:35
Cold Wind***3:12                                            o Seasons (Waiting on You)***3:46
Neighborhood #1 (Tunnels)***4:48                            o Spirit***4:22
Neighborhood #3 (Power Out)***5:12                          o Tin Man***3:14

最后,我的目标是创建一个新列表,该列表现在被打乱,并且新列表不超过一定的持续时间以及其他规范,例如这种格式的三重播放:

Randomised playlist
Artist name: "Song title" (Song duration)
Artist name: "Song title" (Song duration)
...
Artist name: "Song title" (Song duration)
Total duration: <Total duration>.

但这是另一天的战斗。

但是,为了做到这一点,我知道,我必须读入文件的内容,拆分字符串并存储艺术家、他们各自的歌曲以及我假设的每首歌曲持续时间需要是二维阵列。 到目前为止我的代码是这样的:

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

#define MAX_LEN 9999

int main(void) {
 
   char *strFileSummary = "output.txt";
   char strTempData[MAX_LEN];
   char **strData = NULL; // String List
   int i, j, min;
   int noOfLines = 0;

   FILE * ptrSummary = NULL;
   FILE *fp = fopen("songs.txt", "r+");            //this will create and open a new .txt file where the contents will be copied to

   //This will check in case the input .txt file exists or not
   if ((fp = fopen("songs.txt", "r")) == NULL) {
      printf("Um....are you sure this file exists? Maybe try again after obtaining this file.\n");
      exit(0);                                                            //This will exit the program
   }
   
   // Read and store in a string list.
   while(fgets(strTempData, MAX_LEN, fp) != NULL) {
      // Remove the trailing newline character
      if(strchr(strTempData,'\n')){
      strTempData[strlen(strTempData)-1] = '\0';
      }
      strData = (char**)realloc(strData, sizeof(char**)*(noOfLines+1));
      strData[noOfLines] = (char*)calloc(MAX_LEN,sizeof(char));
      strcpy(strData[noOfLines], strTempData);
      noOfLines++;
   }
   
   // Sort the array.
   for(int i= 0; i < (noOfLines - 1); i++) {
      int min = i;
      for(int j = i+1; j < ( noOfLines); j++) {
         if(strcmp(strData[j], strData[min]) < 0) {
            strcpy(strTempData, strData[j]);
            strcpy(strData[j], strData[min]);
            strcpy(strData[min], strTempData);
         }
      }
   }

   // Write it to outfile. file.
   for(int i = 0; i < noOfLines; i++) {
      printf("%s\n",strData[i]);
   }

   fclose(fp);
   return 0;
}

这会产生这个:


00000 Million***3:53
29 #Strafford APTS***4:05
Arcade Fire
Bon Iver
Cold Wind***3:12
Future Islands
Grease***4:35
Neighborhood #1 (Tunnels)***4:48
Neighborhood #3 (Power Out)***5:12
Rebellion (Lies)***5:10
Seasons (Waiting on You)***3:46
Spirit***4:22
Tin Man***3:14
Wake Up***5:39
re: Stacks***6:40

我真的被困住了,我想不出一种正确存储内容的方法,以便我以后可以使用它们,有什么建议/提示吗?

【问题讨论】:

  • 我认为您需要的是一个结构,其中包含您需要的每个信息的字段。然后你可以逐行阅读。在第一行中,您希望找到以下歌曲的艺术家,然后您希望每行都有一首歌,直到找到空行。对于每首歌曲,使用 strstr 搜索 *** 并拆分标题和持续时间。最后为每个歌曲复制艺术家、标题和持续时间在一个新的结构元素中。
  • 诱惑是建议您使用“真实”数据库而不是平面文件:)
  • 是的 - @RobertoCaboni 说的。您需要一个包含歌曲数据子列表的“songsByWriter”结构。然后,您可以在读取数据时创建指向结构的指针列表。首先让它工作,(这样你就可以重新创建原始文件),然后按标题对每个结构歌曲数据进行排序,然后按作者对指针进行排序。
  • 请不要破坏您的帖子。通过在 Stack Exchange 网络上发帖,您已在 CC BY-SA 4.0 license 下授予 Stack Exchange 分发该内容的不可撤销的权利(即无论您未来的选择如何)。根据 Stack Exchange 政策,帖子的非破坏版本是分发的版本,因此,任何破坏行为都将被撤销。如果您想了解更多关于删除帖子的信息,请参阅:How does deleting work?

标签: arrays c string file storing-data


【解决方案1】:

这对于算法和数据结构都是一个很好的问题。有一百万种方法可以解决这个问题。

我建议您考虑输入文件并找到更简单的方法来处理它。我会为潜在的解决方案编写一个伪代码。

我们可以看到艺术家和歌曲被新的线条分开。歌曲中包含特殊字符 asterix。

read the file
get the new line 
if doesn't have * and its includes a-b A-Z then its artist
put artist_name into a variable (in loop)
if the line has * inside it then its a song
you need to parse it in to song_name and duration
strtok *** (or write your own function) 
concatenate "artist_name: song_name duration"
store it inside a string and put it into outputarray
iterate other line
when eof
shuffle output array and write it out to output.txt

这个伪代码肯定可以工作,它比你的方法更容易,因为你不需要弄乱只有 1 个 while 循环的二维数组。我希望这会有所帮助,我在这里需要进一步的帮助。

我已经解决了您的问题,并希望为您提供更好的视力。我使用了上面的psedo代码并生成了这个代码。

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


int isBlank (char const * line)
{
  char * ch;
  int is_blank = -1;

  // Iterate through each character.
  for (ch = line; *ch != '\0'; ++ch)
  {
    if (!isspace(*ch))
    {
      // Found a non-whitespace character.
      is_blank = 0;
      break;
    }
  }

  return is_blank;
}

int main(int argc, char const *argv[])
{
    FILE * fp;

        char * line = NULL;
        size_t len = 0;
        ssize_t read;       
        int end_song_name; // end index of song name
        int start_song_duration; // start index of duration
        char artist_name[100];
        char song_name[100]; // variable to store song name
        char duration[100]; // variable to store duration
        char last_line[200];

        fp = fopen("songs.txt", "r");
        if (fp == NULL)
            exit(EXIT_FAILURE);

        while ((read = getline(&line, &len, fp)) != -1) {

            char * asterix="***"; 
            last_line[0]='\0';
            if(isBlank(line)== -1) // checking blank, if blank skip this iteration
                continue;

            line[strcspn(line, "\n")] = 0; // deleting new line character

            char *ptr;
            if(ptr=strstr(line,asterix)==NULL)  // if no asterix inside the string then its artist name
            {
                strcpy(artist_name,line);
                continue;
            }

            // Song parsing section

            int asterix_index = strcspn(line, asterix); // getting asterix index by strcspn
            int duration_start = asterix_index+3;   // duration starts 3 index after first asterix
        
            for(int i = 0; i < asterix_index; i++)
            {
                song_name[i]=line[i]; // copying line to the song_name till the asterix
            }
            song_name[asterix_index]='\0'; // adding null terminator
            

            // Duration parsing section

            int j=0;
            for(int i = duration_start; i<strlen(line); i++)
            {
                duration[j] = line[i];
                j++;
            }
            duration[j]='\0';

            printf("%s %s %s \n", artist_name, song_name, duration);
            
        }
        

        fclose(fp);
        if (line)
            free(line);
        exit(EXIT_SUCCESS);

    return 0;
}

输出如下:

我希望您尝试理解伪代码,并看到您不需要太多复杂的算法来管理它。考虑一下逐行迭代问题。此外,您还需要对其进行洗牌并将其放入输出 txt 中。我在这里寻求进一步的帮助。

我希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-14
    相关资源
    最近更新 更多