簡體   English   中英

我如何從 char 數組中獲取 int 類型值?

[英]how could i get int type value from char array?

我想從一個輸入文本中獲取三個不同的 int 值(我將輸入“nn_nn_n”)。

例如。 如果我輸入“60_25_5”,我的代碼通過使用下划線(_)並設置“null”將收到的文本分成三部分,我認為三個字符數組(text1、text2、text3)將具有每個值(60、25 , 5) 最后,為了將這些值用作 integer,我使用了 atoi()。

這是我的代碼:

#include <String.h>
#include <stdlib.h>
#include <SoftwareSerial.h> 

void setup {    
   Serial.begin(9600);  
   Serial.println("start");
}
void loop() {
    if(Serial.available()){   
      char *data = Serial.read();// = nn_nn_n
      data[2]='\0';     
      data[5]='\0';     
      char *str ;       
      str = data ;      
      
      char text1[4]; 
      strcpy(text1,str);
      str = data + 3;   
      char text2[4];    
      strcpy(text2, str);
      str = data + 6;   
      char text3[4];    
      strcpy(text3, str);

      int a= atoi(text1);
      int b= atoi(text2);
      int c= atoi(text3);
      Serial.print(a);
      Serial.print(b);
      Serial.print(c);
     }
}

但結果是:

start
000000000000000000000000

我知道我是一個超級菜鳥,但我已經准備好學習你教我的東西,我等待你的評論。 謝謝。

如果您想教事情是如何工作的,請不要使用 arduino IDE,因為沒有很好的工具可以觀察 MCU 在做什么。 我使用 Atmel Studio 向您展示如何調試代碼的某些部分。 這是名為調試器(和模擬器)的工具,它允許查看整個 MCU 部件(查看附圖)。

基本上,您在代碼中存在三個基本誤解:

  • 串行通信的工作原理
  • Serial.read() 如何工作
  • 什么 char *data 是。
  1. 通過串行線路傳輸一個字符需要一些時間。 對於波特率 9600 波特,這次是10*1/baudRate 這大約是 1ms。
    在此期間,MCU 能夠執行loop function 可能數千次。 當然,大多數情況下什么都不做,因為Serial.available()返回 false。 當傳輸消息的第一個字符到達時Serial.available()返回 true 並且條件中的代碼開始執行。 但是整個代碼執行得非常快。 尚未傳輸其他字符。 下一個字符在 1ms 后再次到達。 所以你的代碼只處理一個字符,然后再次等待下一個到達的字符。 因為消息有 8 個字符(6 + CR LF),您的代碼八次寫入值變量ab c並且您得到響應000 000 000 000 000 000 000 000空間未發送,但它表示等待loop ZC4F125264E67ZA8 中的下一個字符。 因此,在每個字符之后,MCU 接收到的打印值000讓我們找出為什么所有變量都被評估為 0 值。

  2. Serial.read()未按預期返回字符串或字符串。 您必須閱讀 Arduino 文檔並理解它。 如果沒有可用數據或消息中的第一個可用字節,Function 返回-1 換句話說,你得到代表到達字符的 ASCII 值的數字。 在您的示例中,您得到第一個值 0x36,因為數字六的 ASCII 值是 0x36('6')。 這是原因,因為我將您的命令char *data = Serial.read();// = nn_nn_nchar *data = '6'; 代表第一個字符到達后的情況。

  3. 這個命令在做什么? (劇透 -在這種情況下非常糟糕)這個命令創建局部變量什么是指向 char 的指針。 此變量在堆棧上創建並占用兩個字節。 您可以在第一行的手表 window 中看到它。 你可以看到這個變量的地址是0x08E6 這個變量是在loop function 中自動創建的,這里是調用Serial.read()返回的插入值。 所以在第一個字符中有值0x36 但請記住,這是指向 char的指針,這意味着數據指針現在指向地址“0x36”。 這很糟糕,真的很糟糕。 地址0x36上有什么。 您可以在 window Memmory1 中看到 MCU memory 的這一部分。 不幸的是,這是 memory 的一部分,保留用於訪問 IO 寄存器。 該寄存器控制 MCU 的硬件,如定時器、轉換器、SPI、IIC、UARTS……向該區域寫入隨機值是非常糟糕的主意。
    data[2]='\0'; 這將嘗試將零寫入0x0038寄存器
    data[5]='\0'這將嘗試將零寫入0x003B寄存器
    在這種情況下,您很幸運,因為您可以看到這部分中的所有寄存器都為零值,並且您沒有破壞任何硬件配置。 所有其他命令都可以通過步進輕松檢查,並且很容易理解您仍然在玩機智的零長度字符串。 所以最終值變量ab c變為零。

(如果MCU是ATMEGA328,所有這些故事情節都是一筆交易) 模擬器視圖

您可以考慮使用 strtok() 來解析數字。 然后仍然使用 atoi() 來獲取您的值。

看這個例子:

https://www.best-microcontroller-projects.com/arduino-strtok.html

void setup(void) {
char *token;
char *mystring = "apples,pears,bananas";
const char *delimiter =",";

   Serial.begin(115200);

   token = strtok(mystring, delimiter);

   while (token != NULL) {
      Serial.println(token);
      token=strtok(NULL, delimiter);
   }

}

void loop(void) {

}

只需使用標准庫:

#include <String.h>
#include <stdlib.h>
#include <SoftwareSerial.h>

#include <stdio.h>

void setup {
    Serial.begin(9600);
    Serial.println("start");
}

void loop() {
    int a, b, c;
    if(Serial.available()){
        char* str = Serial.read(); // any in format of: "##_##_##", Ex: "60_25_5"
        sscanf(text, "%d_%d_%d", &a, &b, &c);
        printf("\nGiven numbers: %d, %d, %d", a, b, c);
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM