c - 当我在笔记本电脑上运行时,我的代码可以工作,但是当我将其上传到 hackerrank 时,我在 strtol 处收到错误

标签 c segmentation-fault

我正在做一个来自 hackerrank 的问题,问题是:https://www.hackerrank.com/challenges/time-conversion/problem

tl;dr 我们将 08:00:00PM 等时间转换为 20:00:00

我从这个网站获取的 str_split 函数:Split string with delimiters in C

首先这是我的完整代码:

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

char** str_split(char* a_str, const char a_delim)
{
    char** result    = 0;
    size_t count     = 0;
    char* tmp        = a_str;
    char* last_comma = 0;
    char delim[2];
    delim[0] = a_delim;
    delim[1] = 0;

    /* Count how many elements will be extracted. */
    while (*tmp)
    {
        if (a_delim == *tmp)
        {
            count++;
            last_comma = tmp;
        }
        tmp++;
    }

    /* Add space for trailing token. */
    count += last_comma < (a_str + strlen(a_str) - 1);

    /* Add space for terminating null string so caller
       knows where the list of returned strings ends. */
    count++;

    result = malloc(sizeof(char*) * count);

    if (result)
    {
        size_t idx  = 0;
        char* token = strtok(a_str, delim);

        while (token)
        {
            assert(idx < count);
            *(result + idx++) = strdup(token);
            token = strtok(0, delim);
        }
        assert(idx == count - 1);
        *(result + idx) = 0;
    }

    return result;
}


char* timeConverse(char* chr)
{
    int del1 = 8;
    int hour = 0;
    char str[3];
    char *result = malloc(10 * sizeof(str));
    char** tokens;

    char s[11];
    for (int i = 0; i < 11; i++)
    {
        s[i] = *(chr + i);
    }

    bool time_of_day = 0; // 0 is morning, 1 is afternoon

    tokens = str_split(s, ':');
    char *endptr;
    hour = strtol(*(tokens), &endptr, 10); // THE MAIN PROBLEM FOR SEGFAULT I THINK?
    free(tokens);

    // check if it is morning or afternoon
    if (s[8] == 'P')
        time_of_day = 1;

    // if it is afternoon add 12 to hour
    if (time_of_day)
    {
        hour += 12;
        //
        // remove the hour from the timer
        memmove(&s[0], &s[0 + 1], strlen(s) - 0);
        memmove(&s[0], &s[0 + 1], strlen(s) - 0);

        // turn hour from int to string and store that to str
        sprintf(str, "%d", hour);
    }

    // remove the last 2 element from the list (PM or AM)
    s[strlen(s) - 1] = 0;
    s[strlen(s) - 1] = 0;

    // add hour to the min and second and store to result
    sprintf(result, "%s%s", str, s);

    // print out the result
    return result;
    free(result);
}

int main(void)
{
    // this is just a test
    char* time = "07:05:45PM";
    char* result = timeConverse(time);
    printf("%s\n", result);
    return 0;
}

这是我的黑客排名代码:

#include <assert.h>
#include <limits.h>
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* readline();

/*
 * Complete the timeConversion function below.
 */

/*
 * Please either make the string static or allocate on the heap. For example,
 * static char str[] = "hello world";
 * return str;
 *
 * OR
 *
 * char* str = "hello world";
 * return str;
 *
 */

char **str_split(char *a_str, const char a_delim) {
  char **result = 0;
  size_t count = 0;
  char *tmp = a_str;
  char *last_comma = 0;
  char delim[2];
  delim[0] = a_delim;
  delim[1] = 0;

  /* Count how many elements will be extracted. */
  while (*tmp) {
    if (a_delim == *tmp) {
      count++;
      last_comma = tmp;
    }
    tmp++;
  }

  /* Add space for trailing token. */
  count += last_comma < (a_str + strlen(a_str) - 1);

  /* Add space for terminating null string so caller
     knows where the list of returned strings ends. */
  count++;

  result = malloc(sizeof(char *) * count);

  if (result) {
    size_t idx = 0;
    char *token = strtok(a_str, delim);

    while (token) {
      assert(idx < count);
      *(result + idx++) = strdup(token);
      token = strtok(0, delim);
    }
    assert(idx == count - 1);
    *(result + idx) = 0;
  }

  return result;
}

char* timeConversion(char* chr) {
    /*
     * Write your code here.
     */
    int del1 = 8;
    int hour = 0;
    char str[3];
    char *result = malloc(10 * sizeof(str));
    char **tokens;

    char s[11];
    for (int i = 0; i < 11; i++) {
      s[i] = *(chr + i);
    }

    bool time_of_day = 0; // 0 is morning, 1 is afternoon

    tokens = str_split(s, ':');
    char *endptr;
    hour = strtol(*(tokens), &endptr, 10);
    free(tokens);

    // check if it is morning or afternoon
    if (s[8] == 'P')
      time_of_day = 1;

    // if it is afternoon add 12 to hour
    if (time_of_day) {
      hour += 12;
      //
      // remove the hour from the timer
      memmove(&s[0], &s[0 + 1], strlen(s) - 0);
      memmove(&s[0], &s[0 + 1], strlen(s) - 0);

      // turn hour from int to string and store that to str
      sprintf(str, "%d", hour);
    }

    // remove the last 2 element from the list (PM or AM)
    s[strlen(s) - 1] = 0;
    s[strlen(s) - 1] = 0;

    // add hour to the min and second and store to result
    sprintf(result, "%s%s", str, s);

    // print out the result
    return result;
    free(result);
}

int main()
{
    FILE* fptr = fopen(getenv("OUTPUT_PATH"), "w");

    char* s = readline();

    char* result = timeConversion(s);

    fprintf(fptr, "%s\n", result);

    fclose(fptr);

    return 0;
}

char* readline() {
    size_t alloc_length = 1024;
    size_t data_length = 0;
    char* data = malloc(alloc_length);

    while (true) {
        char* cursor = data + data_length;
        char* line = fgets(cursor, alloc_length - data_length, stdin);

        if (!line) { break; }

        data_length += strlen(cursor);

        if (data_length < alloc_length - 1 || data[data_length - 1] == '\n') { break; }

        size_t new_length = alloc_length << 1;
        data = realloc(data, new_length);

        if (!data) { break; }

        alloc_length = new_length;
    }

    if (data[data_length - 1] == '\n') {
        data[data_length - 1] = '\0';
    }

    data = realloc(data, data_length);

    return data;
}

它可以在我的电脑上运行,但是当我在 hackerrank 上运行我的代码时,我将代码上传到 timeConversion 函数中,我收到此错误:

 GDB trace:
Reading symbols from solution...done.
[New LWP 11121]
Core was generated by `solution'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  __GI_____strtol_l_internal (
    nptr=0x5847d900 <error: Cannot access memory at address 0x5847d900>, 
    endptr=0x7ffd1f2ba350, base=10, group=<optimized out>, 
    loc=0x7f60be451560 <_nl_global_locale>) at ../stdlib/strtol_l.c:292
#0  __GI_____strtol_l_internal (
    nptr=0x5847d900 <error: Cannot access memory at address 0x5847d900>, 
    endptr=0x7ffd1f2ba350, base=10, group=<optimized out>, 
    loc=0x7f60be451560 <_nl_global_locale>) at ../stdlib/strtol_l.c:292
#1  0x0000555a56bd0d43 in timeConversion (chr=<optimized out>)
    at solution.c:89
#2  0x0000555a56bd0a4e in main () at solution.c:126

我假设 hackerrank 编译器与我的编译器计算机不同。 我使用编译代码 gcc(Debian 8.2.0-12)8.2.0。

最佳答案

您的解决方案根本不需要str_split

直接替换即可

tokens = str_split(s, ';');
char *endptr;
hour = strtol(*(tokens), &endptr, 10); // THE MAIN PROBLEM FOR SEGFAULT I THINK?
free(tokens);

char *endptr;
hour = strtol(s, &endptr, 10);

当然,删除 char** 标记; 以及 int del1 = 8; 无用

关于c - 当我在笔记本电脑上运行时,我的代码可以工作,但是当我将其上传到 hackerrank 时,我在 strtol 处收到错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53971014/

相关文章:

c++ - std::vector 析构函数中的段错误

c - 当我在函数中分配指针时,在这种情况下出现段错误的原因是什么

c - 将 scanf 值传递给结构指针段错误

C:传递二维数组的一维会导致段错误

c - 为什么我的代码中出现段错误?

c - 求 3 个骰子之和等于整数 k 的概率时的分割错误

mysql - 我应该在每次连接关闭后执行 mysql-library-end()

c++ - 阴影的窗口样式?

c - 在 C 程序中包含库 (lsusb)

c - 访问动态分配的元素和数组