当我在笔记本电脑上运行时,我的代码工作,但当我上传到hackerrank时,我在strtol得到错误

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当我在笔记本电脑上运行时,我的代码工作,但当我上传到hackerrank时,我在strtol得到错误相关的知识,希望对你有一定的参考价值。

我正在从hackerrank做一个问题这里是问题:https://www.hackerrank.com/challenges/time-conversion/problem

tl; dr我们花时间在08:00:00 PM并将其转换为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
", 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
", 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] == '
') { 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] == '
') {
        data[data_length - 1] = '';
    }

    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** tokens;int del1 = 8;是无用的

另一答案

问题很可能是main()中的这一行:

char* time = "07:05:45PM";

改成:

char time[] = "07:05:45PM";

在你的解决方案中,time是一个指向文字常量的指针,但split_str()修改它。

一般来说,解决方案是过度设计的;以下将有效:

char* timeConversion(char* s) 
{
    if (s[0] == '1' && s[1] == '2' ) 
    {
        if( s[8] == 'A' )
        {
            s[0] = '0' ;
            s[1] = '0' ;
        } 
    }
    else if( s[8] == 'P' ) 
    {
        s[0] += 1 ;
        s[1] += 2 ;
    }

    s[8] = 0 ;

    return s ;
}

以上是关于当我在笔记本电脑上运行时,我的代码工作,但当我上传到hackerrank时,我在strtol得到错误的主要内容,如果未能解决你的问题,请参考以下文章

无法在以前工作的脚本上实例化类

应用程序在我的设备上运行,但当我将其发布到 Google Play 商店进行 Beta 测试时无法运行

水晶报告问题+甲骨文

Go & Docker:我可以在使用 stdlib 时运行 Go Web 服务器,当我使用自定义包时会出现错误

当我从模块内部运行文件时,文件导入正在工作,但当我通过从外部导入模块来运行文件时则不起作用

在我的笔记本电脑上运行克隆的 nodejs 项目时出错