【问题标题】:C Programming - can't copy string from buffer to given char array using pointersC 编程 - 无法使用指针将字符串从缓冲区复制到给定的字符数组
【发布时间】:2020-07-22 14:51:33
【问题描述】:

我不确定我在哪里搞砸了,所以我给出了每个函数的摘要,以便可以检查我的逻辑!

主程序从命令行获取参数并将它们存储在 char 指针数组中。

运行程序的正确命令是 ./re-do_hw4_prob6 文件名。 (在这种情况下,文件名为 sears_kmart_stores_closing_2019.txt)

检查参数号是否正确后,打开文件。

while 循环将文本字符串从文件复制到缓冲区,直到遇到 NULL。

然后调用函数getState()。打印状态。

文件已关闭。

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

#include "redo_hw4_functs.h"


int main(int argc, char* argv[])
{
    char** states;
    FILE* pFile;
    char buffer[80];
    int i = 0;
    
    
    
    if(argc < 2){
        printf("Too few arguments! \n");
    }
    else if(argc > 2){
        printf("Too many arguments! \n");
    }
    
   
    pFile = fopen(argv[1], "r");
    
    states = malloc(50*sizeof(char));
    
    for (i = 0; i < 50; i++)
    {
    states[i] = malloc(3*sizeof(char));
    
    while(fgets(buffer, sizeof(buffer), pFile) != NULL)
    {
        
        getState(states[i], buffer);
        
        printf("State: %s \n", states[i]);
        
    }
        
        
        }
    
    
    
    fclose(pFile);
    
}

getState() 函数接受两个字符数组。一个可以读取另一个也可以复制。

它使用逗号、制表符和新行作为分隔符来标记正在读取的字符串。 -> ",\t\n"

在最后一个标记上,它将最后两个字符复制到空字符串数组中。

//accepts a line of string formatted as expected and stores the store state in char file ¡OJO! This is the hardest one because you cant rely on delimeters alone to find state 
void getState(char strState[], char strLine[])
{
    int i;
    char* token;
    char delim[] = ",\t\n";
    
    token = strtok(strLine, delim);
    token = strtok(strLine, delim);
    token = strtok(strLine, delim);
    
    for(i = (strlen(token) - 2); i < strlen(token); i++)
    {
        strState[i] =token[i];
    }
    
}

我还把我的其他功能也加进去了,看看有没有其他错误需要改正。

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


#include "redo_hw4_functs.h"



//accepts a line of string formatted as expected and stores the store name in char file
void getName(char strName[], char strLine[])
{
    char* token;
    char delim[] = " ,\t\n";
    
    token = strtok(strLine, delim);
    
    while(token != NULL)
    {
        if(strcmp(token, "sears") == 0 || strcmp(token, "kmart"))
        {
            strcpy(strName, token);
            break;
        }
        
        token = strtok(NULL, delim);
    }
    
    
    
    
}

//accepts a line of string formatted as expected and stores the store address in char file
void getAddress(char strAddress[], char strLine[])
{
    
    char* token;
    char delim[] = ",\t\n";
    
    token = strtok(strLine, delim);
    
    while(token != NULL)
    {
        if(isdigit(token[0]) && isalpha(token[sizeof(token)-1]))
        {
            strcpy(strAddress, token);
            break;
        }
        
        token = strtok(NULL, delim);
    }
    
}

//accepts a line of string formatted as expected and stores the store city in char file
void getCity(char strCity[], char strLine[])
{
    int i;
    char* token;
    char delim[] = ",\t\n";
    
    token = strtok(strLine, delim);
    token = strtok(strLine, delim);
    token = strtok(strLine, delim);
    
    for(i = 0; i < (strlen(token) - 3); i++)
    {
        strcpy(strCity[i], token[i]);
    }
    
    
    
    
    
    
}

//accepts a line of string formatted as expected and stores the store state in char file ¡OJO! This is the hardest one because you cant rely on delimeters alone to find state 
void getState(char strState[], char strLine)
{
    int i;
    char* token;
    char delim[] = ",\t\n";
    
    token = strtok(strLine, delim);
    token = strtok(strLine, delim);
    token = strtok(strLine, delim);
    
    for(i = (strlen(token) - 2); i < strlen(token); i++)
    {
        strcpy(strState[i], token[i]);
    }
    
}

以下是要读取的输入文本示例:

Kmart, 217 Forks Of River Pkwy, Sevierville TN
Kmart, 4110 E Sprague Ave, Spokane WA
Kmart, 1450 Summit Avenue, Oconomowoc WI
Sears, 2050 Southgate Rd, Colorado Spgs CO
Sears, 1650 Briargate Blvd, Colorado Spgs CO
Sears, 3201 Dillon Dr, Pueblo CO

这是程序预期输出的示例:

州:TN 州:WA 州:威斯康星 状态:CO 状态:CO 状态:CO

这是程序输出的示例:

【问题讨论】:

  • 注意:“检查参数号是否正确后,打开文件。” --> 即使argc 不正确,也会尝试打开文件。
  • states[i] 没有意义 - states 未初始化。
  • 已初始化状态,但我似乎无法将状态缩写复制到它。 @KamilCuk
  • states = malloc(50*sizeof(char)); 应该是 states = malloc(50*sizeof(char*)); 。或者,更好的是states = malloc(50 * sizeof *states);
  • @ForrestBrown 不要使用图像,并发布预期输出,而不是实际输出。

标签: c strtok


【解决方案1】:

我假设您不仅需要状态,还需要所有其他字段,以便以后处理它们。

下面的代码可能和你的有很大不同,但我认为使用单个函数读取每条记录更容易。

函数read_data()从文件指针fp读取数据并将它们存储在data中,这是一个指向预定义结构data_t的指针。

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

#define BUFFER_SIZE 1024

typedef struct {
    char name[64];
    char addr[64];
    char city[64];
    char state[8];
} data_t;

int read_data(FILE *fp, data_t *data) {
    char buffer[BUFFER_SIZE];

    // Read a record. If end-of-file is read, return -1.
    if (fgets(buffer, BUFFER_SIZE, fp) == NULL) {
        return -1;
    }

    char delim[] = ",\t\n";

    // Find the name of the record.
    char *token = strtok(buffer, delim);
    strcpy(data->name, token);

    // Find the address of the record.
    token = strtok(NULL, delim);
    while (*token == ' ') {
        ++token;
    }
    strcpy(data->addr, token);

    // Find the city and status of the record.
    // We cannot split them by strtok() easily, so we handle it later.
    token = strtok(NULL, delim);
    while (*token == ' ') {
        ++token;
    }

    // Find the position of the state.
    char *ptr = token;
    while (*ptr != '\0') {
        ++ptr;
    }
    ptr -= 2;
    strcpy(data->state, ptr);

    // Use NULL to separate the city and the state so that we can use strcpy().
    while (*(ptr - 1) == ' ') {
        --ptr;
    }
    *ptr = '\0';

    // Copy the city field.
    strcpy(data->city, token);
    return 0;
}

int main(int argc, char *argv[]) {
    if (argc != 2) {
        fprintf(stderr, "The number of arguments is incorrect.\n");
        fprintf(stderr, "Usage: %s filename\n", argv[0]);
        return -1;
    }
    FILE *fp = fopen(argv[1], "r");
    data_t *data = malloc(sizeof(data_t));
    while (read_data(fp, data) == 0) {
        printf("State: %s\n", data->state);
    }
    free(data);
    fclose(fp);
    return 0;
}

读取数据的方式是硬编码的,所以如果输入格式不同,你可能需要更改read_data()的内容,但它对你的示例输入很有效。

【讨论】:

    猜你喜欢
    • 2015-10-29
    • 2012-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-04
    • 1970-01-01
    • 2011-11-01
    • 1970-01-01
    相关资源
    最近更新 更多