LeetCode 171 Excel Sheet Column Number(Excel的列向表数字)

本文介绍了一种将Excel列标题转换为对应数字的方法,并通过示例解释了其背后的数学原理。提供了两种实现该功能的C++代码示例,探讨了不同编译环境下可能遇到的问题及解决方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

翻译

给定一个出现在Excel表格上的列表标题,返回它的正确行数。  

例如:
    A -> 1
    B -> 2
    C -> 3
    ...
    Z -> 26
    AA -> 27
    AB -> 28 

原文

Given a column title as appear in an Excel sheet, return its corresponding column number.

For example:
    A -> 1
    B -> 2
    C -> 3
    ...
    Z -> 26
    AA -> 27
    AB -> 28 

分析

有了上一题的经验,这次要容易得多了。它的题意也能理解了,就是从上面的实例左侧字符转换成右侧的数字。大家可以看看上一题:LeetCode 168 Excel Sheet Column Title(Excel的列向表标题)

下面是上一题的博客截图,我举了一个进制转换的例子,但是没有说的很明确,那么就在这一题里充分说明一下好了,大家请继续往下看。

这里写图片描述

这里写图片描述

相信有了这个示例,大家就可以秒懂了。

然后我就写了如下代码:

#include <iostream>
using namespace std;

int exponent(int x, int y) {
    int answer = 1;
    for(int i = 0; i < y; ++ i) {
        answer *= x;
    }
    return answer;
}

int titleToNumber(string s) {
    int n = 0, len = s.length();
    for(int i = 0; i < s.length(); ++ i) {
        char c = s[i];
        int chara = c - 'A' + 1;
        n += chara * exponent(26, len - 1 - i);
    }
    return n;
}

int main() {
    cout<<titleToNumber("AAB");
    return 0;
}

输出结果是

704

这是正确的,后来我改成了如下代码:

#include <iostream>
#include <cmath>
using namespace std;

int titleToNumber(string s) {
    int n = 0, len = s.length();
    for(int i = 0; i < s.length(); ++ i) {
        char c = s[i];
        int chara = c - 'A' + 1;
        n += chara * pow(26, len - 1 - i);
    }
    return n;
}

int main() {
    cout<<titleToNumber("AAB");
    return 0;
}

输出是:

703

于是我就纳闷了,后来我从CodeBlocks换到饿了Visual Studio就成了704了,704是正确的。

这里写图片描述

而在CB中把代码改成:

n += chara * (int)pow(26.0, len - 1 - i);

结果反而成了702了。

希望大家发现问题的在下面留言告诉我啊……

如果换成了double的话,在CB中也是OK的:

#include <iostream>
#include <cmath>
using namespace std;

double titleToNumber(string s) {
    double n = 0, len = s.length();
    for(int i = 0; i < s.length(); ++ i) {
        char c = s[i];
        double chara = c - 'A' + 1;
        double a = len - 1 - i;
        n += chara * pow(26.0, a);
    }
    return n;
}

int main() {
    cout<<titleToNumber("AAB");
    return 0;
}

问题是我好想知道它们在CB和VS内部是如何走的……

代码

class Solution {
public:
    int titleToNumber(string s) {
        int n = 0, len = s.length();
        for (int i = 0; i < s.length(); ++i) {
            char c = s[i];
            int chara = c - 'A' + 1;
            n += chara * pow(26, len - 1 - i);
        }
        return n;
    }
};
<think>好的,用户的问题是关于如何确保代码中的A和B名称与Excel文件的头一致。我需要先理解用户的具体需求和上下文。用户提到了引用[1]、[2]、[3],其中涉及VC++、PHP处理Excel的方法,以及名称转换的算法。用户可能在用某种编程语言处理Excel,需要动态匹配头,避免硬编码名导致的错误。 首先,我需要整理引用中的信息。引用[1]提到通过COM接口操作Excel,生成相关类来读取头。引用[2]是PHP根据头字段自动匹配数据,可能需要动态获取头数组。引用[3]是关于号转字母名称的算法,比如将1转为A,27转为AA,这可能用于处理的位置。 用户的问题是确保代码中的名(如A、B)与实际Excel头一致。可能用户之前是硬编码字母,但头顺序可能变化,导致数据错位。例如,用户代码中写死A为“姓名”,但Excel中“姓名”可能在B,这样就会出错。 接下来,我需要思考解决方案。可能的步骤包括:1. 动态读取Excel头,存储为数组或字典。2. 根据需要的字段名(如“姓名”、“年龄”)查找对应的索引。3. 使用索引来读取数据,而不是固定的A、B字母。 引用[3]的号转字母的方法可能用于将找到的索引转换为Excel字母,但更高效的方式可能是直接使用索引来访问数据,避免转换。例如,在PHP中,使用数字位置,而不是字母。 需要考虑不同编程语言的实现方式。例如,在VC++中,可能需要通过COM接口获取range对象,遍历第一行单元格的值,找到匹配的索引。在PHP中,使用如PhpSpreadsheet库,读取头行,然后查找字段名对应的号。 此外,用户可能需要处理头名称可能的大小写、空格等不一致问题,这时需要进行规范化处理,比如转为小写,去除空格后再比较。 总结步骤:读取头行→遍历头字段→记录目标字段的索引→使用索引读取数据。这样无论Excel顺序如何变化,只要头名称正确,就能正确匹配。 还需要考虑异常情况,比如头中不存在需要的字段,这时应抛出错误或提示用户检查Excel文件。 最后,根据引用[2]中的PHP示例,可以建议用户使用类似的方法,动态建立字段到的映射,而不是依赖固定字母。引用[3]的算法可能在需要将号转为字母时使用,但多数情况下直接使用索引更直接。</think>### 确保代码中的名称匹配Excel头的方法 #### 1. **动态获取头名称** - **步骤**: 1. **读取Excel第一行作为头**:通过编程接口(如VC++的COM组件或PHP的PhpSpreadsheet)获取第一行单元格的值,保存为数组或字典[^1][^2]。 2. **规范化头字段**:去除首尾空格、统一大小写(例如全转小写),避免因格式差异导致匹配失败[^2]。 ```python # Python示例(使用openpyxl库) from openpyxl import load_workbook wb = load_workbook("data.xlsx") sheet = wb.active headers = [cell.value.strip().lower() for cell in sheet[1]] ``` #### 2. **建立字段与索引的映射** - **方法**: - 遍历头数组,记录目标字段(如“姓名”“年龄”)对应的索引。例如: ```python target_columns = {} for idx, header in enumerate(headers): if header == "姓名": target_columns["name"] = idx # 记录索引 elif header == "年龄": target_columns["age"] = idx ``` - 若字段不存在,抛出异常提示用户检查头。 #### 3. **使用索引读取数据** - **替代固定字母**:通过记录的索引访问数据,而非硬编码`A`、`B`: ```python for row in sheet.iter_rows(min_row=2): name = row[target_columns["name"]].value # 动态获取“姓名” age = row[target_columns["age"]].value # 动态获取“年龄” ``` #### 4. **号与字母转换(可选)** - 若需生成类似`A`、`B`的标识(如生成报告),可参考LeetCode号转字母算法[^3]: ```python def column_number_to_letter(n): letters = [] while n > 0: n -= 1 letters.append(chr(n % 26 + ord('A'))) n = n // 26 return ''.join(reversed(letters)) ``` #### 5. **完整流程示例(PHP)** ```php // 引用PhpSpreadsheet库 use PhpOffice\PhpSpreadsheet\IOFactory; $spreadsheet = IOFactory::load("data.xlsx"); $sheet = $spreadsheet->getActiveSheet(); // 读取头并建立映射 $headerRow = $sheet->getRowIterator(1)->current(); $cellIterator = $headerRow->getCellIterator(); $headerMap = []; foreach ($cellIterator as $cell) { $headerName = strtolower(trim($cell->getValue())); $headerMap[$headerName] = $cell->getColumn(); } // 检查必需字段是否存在 if (!isset($headerMap['姓名']) || !isset($headerMap['年龄'])) { throw new Exception("Excel头缺少必要字段"); } // 读取数据行 foreach ($sheet->getRowIterator(2) as $row) { $name = $sheet->getCell($headerMap['姓名'] . $row->getRowIndex())->getValue(); $age = $sheet->getCell($headerMap['年龄'] . $row->getRowIndex())->getValue(); } ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值