如何在单个文件中读取字符串的最后n个字符?

时间:2017-12-25 08:16:39

标签: c arrays char fgets

我想读取文件中第一行的最后n个字符" passwordhashes.txt"。如果" $ 1 $$"在一行中检测到,我想打印该行的最后26个字符,如果" $ 6 $$"而是检测到,我想打印该行的最后90个字符。如果检测到md5,则以下代码返回前26个字符,如果检测到sha512,则返回前90个字符,但这不是我想要的。

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

int printDataError()
{      
  printf("Data error: Invalid entry found (Skipped)\n");
}    

int main(void)
{
  char buf[1024];
  char **arr2 = NULL;
  int size2 = 0;
  FILE *f2;
  f2 = fopen("passwordhashes.txt", "r");

  while(fgets(buf, 1024, f2)) {
    size2++;
    arr2 = realloc(arr2, sizeof(char*) * size2);
    arr2[size2 - 1] = strdup(buf);
  }

  char line[1000];
  char hash[1000];      
  char md5[5]= "$1$$";
  char sha512[5]="$6$$";
  char *ret;
  char *ret2;

  // Read file line by line     
  for(int j = 0; j < size2; j++) {      
    memset(hash, '\0', sizeof(hash));
    strcpy(line, arr2[j]);

    // Search for md5 
    md5[4]='\0';
    ret = strstr(line, md5);

    // Search for sha512
    sha512[4]='\0';
    ret2 = strstr(line, sha512);

    if (ret) {
      strncpy(hash, line,26);     
      printf("Line %d hash: %s\n", j+1,hash);
    } else if (ret2) {
      strncpy(hash, line,90);    
      printf("Line %d hash: %s\n", j+1,hash);    
    } else {
      printDataError();
    }
  }
  return 0;
}

passwordhashes.txt中的几行(此文件中共有219128行,所以我只列出几行):

a:$1$$Ij31LCAysPM23KuPlm1wA/
a:$6$$ek/ucQg0IM8SQLyD2D66mpoW0vAF26eA0/pqoN95V.F0nZh1IFuENNo0OikacRkDBk5frNqziMYMdVVrQ0o.51
aah:$1$$bh5o1cAKfH43fc/B1.AjF0
aah:$6$$jdxDww2LkNSlQPmWe5iDRAoBBT5IXa9241nN2bcm2Aukdrr4iH27Y6dj801MjLFaDQxbDBNxY4jvlXdIemiCY/
aahed:$1$$zA2Ef92JR9W7kqAf8Km5B0
aahed:$6$$mYQU7f3NL9Dysccvwv2BAyiCb/gxh9lN1gGnC9sa2uwHGX9VVb7jp3b7u/EZbdObqWrRFgiOLcRn7PEW1cOcz.
aahing:$1$$lDHqezDzqgN4GXlWys7LB0
aahing:$6$$rqJD4oAdyTJ3EasAFN.FeNwTFiCIIklFEo2YcxSS1X5Vutrlqu7r91c4G0PnsVAISIUIBX9.d.8riuVMmKddy/

1 个答案:

答案 0 :(得分:1)

这是strncpy的简单重拍,它是一个标准函数,可以将n个字符从源复制到目标。 此功能复制n中最后一个src个字符并将其复制到dest。如果n大于src的长度,则不会执行任何操作。

#include <string.h>
void strlncpy(char *dest , char *src , size_t n){
    size_t len = 0;
    if(!dest || !src || (len = strlen(src)) < n)
            return;
    char *p = src + (len - n);
    strcpy(dest , p);
}

以下是使用strlncpy

重新制作您的计划
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define DELIM ':'
#define MD5_SIGN "$1$$"
#define SHA512_SIGN "$6$$"
#define MD5_LEN 22 /* I changed this to get only the hash. */
#define SHA512_LEN 86

void strlncpy(char *dest , const char *src , size_t n){
    size_t len = 0;
    if(!dest || !src || (len = strlen(src)) < n)
            return;
    char *p = src + (len - n);
    strcpy(dest , p);
}

int main(){
ssize_t r = 0;
size_t n =0;
char *o = NULL , *p  = NULL , hash[100];
FILE *fp = NULL;
if((fp = fopen("passwordhash.txt", "r")) == NULL){
    printf("cannot open file!\n");
    return -1;
}
while((r = getline(&o , &n , fp)) != -1){
        p = o;
        /* Print the raw text. */
        printf("RAW TEXT:: ");
        while(*p != DELIM){
                putchar(*p);
                ++p;
        }
        putchar('\n');
        p = o; 
        if(strstr(p , MD5_SIGN)){
                /* plus one is for the newline. */
                strlncpy(hash , p , MD5_LEN + 1);
                hash[strlen(hash)-1] = '\0'; /* remove newline. */
                printf("MD5 HASH:: %s\n" , hash); 
        }else if(strstr(p , SHA512_SIGN)){
                strlncpy(hash , p , SHA512_LEN + 1);
                hash[strlen(hash)-1] = '\0'; 
                printf("SHA512 HASH:: %s\n" , hash);
        }
}
fclose(fp); // Also close files!
return 0;
}