有没有一种快速的方法来获取放置在数组中的最后一个元素?

时间:2020-07-30 12:26:22

标签: arrays c char fgets c-strings

我使用fgetsstdin读取一行并将其保存在char数组中,我想获取我写的该行的最后一个字母,应该是在\n\0之前的数组中。

例如,如果我有一个char line[10]并在终端机1stLine上书写,有没有一种快速的方法来获取字母e,而不仅仅是循环使用它?

我看到了这篇帖子How do I print the last element of an array in c,但我认为它对我不起作用,即使我只是创建数组而不用fgets填充数组,sizeof line也已经是10,因为数组中已经有东西

我知道它不是java,而且我不能只是.giveMeLastItem(),但是我想知道是否有比在\n前面的char循环直到获得我写的最后一个字母更聪明的方法< / p>

代码类似于

char command[6];
fgets(command,6,stdin);

7 个答案:

答案 0 :(得分:2)

如果您知道哨兵值,例如:\0(或\n,或与此有关的任何值),并且想要紧接其前的元素的值,则可以

  • 使用strchr()来确定前哨的位置,然后
  • 获取retPtr-1的地址并取消引用以获取所需的值。

答案 1 :(得分:2)

一旦只有数组,就没有其他方法可以这样做了。您可以使用strlen(line),然后根据此索引获取最后一个字符的位置,但这基本上是完全相同的(遍历数组)。

char lastChar = line[strlen(line)-1];

时间复杂度为O(n),其中n是输入长度。

您可以通过char输入将输入法更改为char并计算长度或存储最后一个输入。像这样的每个O(1)方法都使用O(n)之前的时间(例如,对于每个读取的字符,n(O)(1)次)。但是除非您必须真正加快优化速度(在使用用户输入时就不必这样做),否则应该使用strlen(line)之类的函数在数组上循环(并在多次使用时存储结果) )。

编辑: Sourav Ghosh提到的strchr()函数的功能完全相同,但是您可以/必须指定终止字符。

答案 2 :(得分:2)

有很多不同的方法来检查fgets()所读取的行:

  • 首先,您应该检查fgets()的返回值:NULL的返回值表示到达文件末尾或发生某种错误以及目标数组的内容未定义。还建议使用更长的数组。

      char command[80];
      if (fgets(command, sizeof command, stdin) == NULL) {
          // end of file or read error
          return -1;
      }
    
  • 您可以用len = strlen(command)计算字符数,如果该长度os不为零(*),则command[len - 1]是从文件读取的最后一个字符,应为{{ 1}}(如果该行少于5个字节)。剥离换行符需要测试:

    '\n'
  • 您可以使用 size_t len = strlen(command); if (len > 0 && command[len - 1] == '\n') command[--len] = '\0'; 来查找换行符(如果与strchr()一起出现),如果存在换行符,则可以通过以下方式剥离它:

    char *p strchr(command, '\n');
  • 您还可以用 char *p = strchar(command, '\n'); if (p != NULL) *p = '\0'; 计算集合"\n"中no的字符数。 pos = strcspn(command, "\n")将指向换行符或空终止符。因此,您可以使用以下命令删除结尾的换行符:

    pos
  • 您还可以编写一个简单的循环:

      command[strcspn(command, "\n")] = '\0';  // strip the newline if any
    

(*) char *p = command; while (*p && *p != '\n') p++; *p = '\n'; // strip the newline if any 可以返回strlen(command),如果文件在行的开头包含嵌入的空字符。 0将空字节视为普通字符,它将继续将字节读取到数组中,直到读取了fgets()个字节或读取了换行符为止。

答案 3 :(得分:1)

一种简单的方法可以采用以下方式

char last_letter = command[ strcspn( command, "\n" ) - 1 ];

提供的字符串不为空或仅包含换行符'\n'

这是一个示范性的程序。

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

int main(void) 
{
    enum { N = 10 };
    char command[N];
    
    while ( fgets( command, N, stdin ) && command[0] != '\n' )
    {
        char last_letter = command[ strcspn( command, "\n" ) - 1 ];
        printf( "%c ", last_letter );
    }
    
    putchar( '\n' );
    
    return 0;
}

如果要输入以下字符串序列

Is
there
a
quick
way
to
get
the
last
element
that
was
put
in
an
array?

那么输出将是

s e a k y o t e t t t s t n n ? 

答案 4 :(得分:1)

最快的方法是保留这样的引用数组:

long ref[]

和ref [x]包含第x行最后一个字符的文件偏移量。在文件开头保存此引用后,您将执行以下操作:

fseek(n*sizeof(long))
long ref = read_long()
fseek(ref)
read_char()

我认为这是读取第n行末尾最后一个字符的最快方法。

答案 5 :(得分:1)

除了其他好的例子。

另一种方法是使用fscanf() / scanf()%n格式说明符将输入字符串后到目前为止的已读取字符数写入自变量。

然后将这个数字减一,并将其​​用作command的索引:

char command[6];
int n = 0;

if (fscanf(stdin, "%5[^\n]" "%n", command, &n) != 1)
{
    fputs("Error at input!", stderr);
    // error routine.
}

getchar();

if (n != 0)
{
    char last_letter = command[n-1];
}

#include <stdio.h>

int main (void)
{
    char command[6];
    int n = 0;

    if (fscanf(stdin, "%5[^\n]" "%n", command, &n) != 1)
    {
        fputs("Error at input!", stderr);
        // error routine.
    }

    getchar();
    
    if (n != 0)
    {
        char last_letter = command[n-1];
        putchar(last_letter);
    }

    return 0;
}

执行:

./a.out
hello
o

答案 6 :(得分:1)

我对上述三种从流中读取一条线并测量其长度的方法进行了快速测试。我读了/ usr / share / dict / words 100次,并用clock()/ 1000测量:

fgets + strlen = 420
getc = 510
fscanf with " 100[^\n]%n" = 940

这很有意义,因为fgets和strlen仅执行2次调用,getc每个字符进行一次调用,而fscanf可以进行一次调用,但是设置了很多机制来处理复杂格式,因此产生了更多开销。请注意,以fscanf格式添加的空间将跳过上一行的换行符。