2017-01-09 3 views
2

ich zur Zeit einen FTP-Server schreibe und ich brauche die IP und den Port von einem Remote-Server von einem Eingangs String-Puffer in folgendem Format zu analysieren:Linux sscanf Funktion füllt nicht variabel

xxx,xxx,xxx,xxx,yyy,zzz 

wo:

  • xxx steht für eine IP-Adresse in dezimaler Oktett
  • yyy ist rund ((Remote-Port-Nummer)/256)
  • zzz ist (Remote-Portnummer)% 256

Zum Beispiel: 127,0,0,1,123,64 bedeutet ip = 127.0.0.1 und port = 31552.

ich derzeit sscanf verwenden die folgenden Felder aus dem Eingabestring Puffer zu extrahieren:

sscanf(str, "%u,%u,%u,%u,%u,%u", ret_ip, &ip[0], &ip[1], &ip[2], &temp1, &temp2) == 6 

wo:

  • str ist der Eingangspuffer
  • ret_ip ist vom Typ uint32_t
  • ip's sind vom Typ uint32_t
  • TEMP1 und TEMP2 sind vom Typ unsigned short int

Beispielcode:

#include <stdio.h> 
#include <netdb.h> 
int main(int argc, char *argv[]) 
{ 
    uint32_t ip[4]; 
    unsigned short int temp, temp1; 

    if (sscanf("127,0,0,1,142,214", "%u,%u,%u,%u,%u,%u", &ip[0], &ip[1], &ip[2], &ip[3], &temp, &temp1) == 6) 
    { 
     printf("%u : %u", temp, temp1); 
    } 

    return (0); 
} 

Mein Problem ist, dass für gültige Zeichenfolge, wird der Wert von temp1 ist immer 0 (Null), dh alle anderen Variablen werden entsprechend der Zeichenkette mit Ausnahme der temp1 gefüllt. Ich würde jede Hilfe schätzen.

Antwort

4

scanf ist nicht so fehlerverzeihend Format-Spezifizierer Mismatchs wie printf ist. Die Spezifizierer müssen genau übereinstimmen, oder Sie rufen nicht definiertes Verhalten auf.

Für unsigned short%hu verwenden. %u ist für unsigned int.

Es gibt keine direkten Formatbezeichner für Typen wie uint32_t. Sie müssen use a macro from inttypes.h: "%" SCNu32.

Alle zusammen:

if (sscanf(str, "%" SCNu32 ",%" SCNu32 ",%" SCNu32 ",%" SCNu32 ",%hu,%hu", ret_ip, &ip[0], &ip[1], &ip[2], &temp1, &temp2) == 6) 
+0

Danke für die Hilfe, die% hu Spezifizierer hat den Trick. – dotSK

-1

Followling ist mein Code, und drucken korrekte Ergebnisse zu funktionieren scheint.

char sentence []="127,0,0,1,123,64"; 
    uint16_t ret_ip; 
    uint16_t ip1, ip2, ip3; 
    uint16_t temp1, temp2; 

    sscanf(sentence, "%d,%d,%d,%d,%d,%d", &ret_ip, &ip1, &ip2, &ip3, &temp1, &temp2); 

    printf("%d, %d\n", temp1, temp2); 
+0

'% d' ist für' int'. Es ist ein Fehler, es für 'uint16_t' zu verwenden. –

1

Im Folgenden werden diese Antwort haben die zur Verfügung stehenden Antworten vergleichen:

  • Extrahieren der IP-Adresse Oktetts als unsigned char und sie dann speichern als eine einzige IP-Adresse Größe uint_32 stattdessen eine Reihe von mit von uint_32. Weitere Informationen finden Sie unter this post.
  • Validierung gegen den sscanf Ausgang.
  • Der %hu Scan-Code wird zum Lesen unsigned short und der %hhu Scan-Code zum Lesen unsigned char verwendet.
  • Überprüfen des Prozesses der IP-Adressumwandlung von string zu unitt_32inet_pton verwenden und zu unitt_32stringinet_ntop verwenden. Lesen Sie this section von Beejs Netzwerkbuch, wenn Sie mehr erfahren möchten.

und hier ist der Code:

#include <stdio.h> 
#include <stdlib.h> 
#include <arpa/inet.h> 
int main(int argc, char *argv[]){ 
    unsigned char ip_octects[4] = {0, 0, 0, 0}; 
    uint32_t ip = 0; 
    unsigned short r1 = 0, r2 = 0; 
    unsigned char *str_c = "127,0,0,1,142,214"; 

    if(sscanf(str_c, "%hhu,%hhu,%hhu,%hhu,%hu,%hu", &ip_octects[0], 
        &ip_octects[1], &ip_octects[2], &ip_octects[3], &r1, &r2) == 6){ 

     printf("Extracted ip : port: %hhu.%hhu.%hhu.%hhu:%hu:%hu\n", 
       ip_octects[0], ip_octects[1], ip_octects[2], ip_octects[3], r1, r2); 

     ip = ip_octects[0]  | ip_octects[1] << 8 | 
      ip_octects[2] << 16 | ip_octects[3] << 24; 
     printf("unit32_t ip value: %zu\n", ip); 

     /* We're done but lets verify the results using inet_pton() and inet_ntop() */ 
     unsigned char *str_d = "127.0.0.1"; 
     char str[INET_ADDRSTRLEN]; 
     struct sockaddr_in sa; 
     if(inet_pton(AF_INET, str_d, &(sa.sin_addr)) < 1){ 
      perror("error: invalid input for inet_pton"); exit(1); 
     } 
     printf("inet_pton ip value: %zu\n",sa.sin_addr); 
     if(inet_ntop(AF_INET, &(sa.sin_addr), str, INET_ADDRSTRLEN) == NULL){ 
      perror("error: invalid input for inet_ntop"); exit(1); 
     } 
     printf("inet_ntop str value: %s\n", str); 
    } 
    else{ 
     perror("error: invalid input for sscanf"); exit(1); 
    } 
    return (0); 
}